Skip to content

Commit

Permalink
feat: more Zniffer polishing (#6863)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored May 21, 2024
1 parent 5269c9f commit fcae050
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 20 deletions.
27 changes: 25 additions & 2 deletions docs/api/zniffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ interface ZnifferOptions {
* Supported regions and their names have to be queried using the `getFrequencies` and `getFrequencyInfo(frequency)` commands.
*/
defaultFrequency?: number;

/** Limit the number of frames that are kept in memory. */
maxCapturedFrames?: number;
}
```

Expand Down Expand Up @@ -250,6 +253,14 @@ type ZWaveFrame =
)
>
)
// Broadcast frame. This is technically a singlecast frame,
// but the destination node ID is always 255 and it is not routed
| {
type: ZWaveFrameType.Broadcast;
destinationNodeId: typeof NODE_ID_BROADCAST;
ackRequested: boolean;
payload: Buffer | CommandClass;
}
| {
// Multicast frame, not routed
type: ZWaveFrameType.Multicast;
Expand All @@ -275,6 +286,7 @@ type ZWaveFrame =
} | {
type: ZWaveFrameType.ExplorerInclusionRequest;
networkHomeId: number;
payload: Buffer | CommandClass;
})
// Common fields for all explorer frames
& {
Expand Down Expand Up @@ -313,12 +325,21 @@ type LongRangeFrame =
}
// Different kinds of Long Range frames:
& (
{
| {
// Singlecast frame
type: LongRangeFrameType.Singlecast;
ackRequested: boolean;
payload: Buffer | CommandClass;
} | {
}
| {
// Broadcast frame. This is technically a singlecast frame,
// but the destination node ID is always 4095
type: LongRangeFrameType.Broadcast;
destinationNodeId: typeof NODE_ID_BROADCAST_LR;
ackRequested: boolean;
payload: Buffer | CommandClass;
}
| {
// Acknowledgement frame
type: LongRangeFrameType.Ack;
incomingRSSI: RSSI;
Expand Down Expand Up @@ -401,6 +422,7 @@ enum ZWaveFrameType {
ExplorerInclusionRequest,
BeamStart,
BeamStop,
Broadcast,
}
```

Expand All @@ -412,6 +434,7 @@ enum LongRangeFrameType {
Ack,
BeamStart,
BeamStop,
Broadcast,
}
```

Expand Down
35 changes: 26 additions & 9 deletions packages/core/src/capabilities/Protocols.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,35 @@ export enum ZnifferProtocolDataRate {
LongRange_100k = 0x03,
}

/**
* Converts a ZnifferProtocolDataRate into a human-readable string.
* @param includeProtocol - Whether to include the protocol name in the output
*/
export function znifferProtocolDataRateToString(
rate: ZnifferProtocolDataRate,
includeProtocol: boolean = true,
): string {
switch (rate) {
case ZnifferProtocolDataRate.ZWave_9k6:
return "Z-Wave, 9.6 kbit/s";
case ZnifferProtocolDataRate.ZWave_40k:
return "Z-Wave, 40 kbit/s";
case ZnifferProtocolDataRate.ZWave_100k:
return "Z-Wave, 100 kbit/s";
case ZnifferProtocolDataRate.LongRange_100k:
return "Z-Wave Long Range, 100 kbit/s";
if (includeProtocol) {
switch (rate) {
case ZnifferProtocolDataRate.ZWave_9k6:
return "Z-Wave, 9.6 kbit/s";
case ZnifferProtocolDataRate.ZWave_40k:
return "Z-Wave, 40 kbit/s";
case ZnifferProtocolDataRate.ZWave_100k:
return "Z-Wave, 100 kbit/s";
case ZnifferProtocolDataRate.LongRange_100k:
return "Z-Wave Long Range, 100 kbit/s";
}
} else {
switch (rate) {
case ZnifferProtocolDataRate.ZWave_9k6:
return "9.6 kbit/s";
case ZnifferProtocolDataRate.ZWave_40k:
return "40 kbit/s";
case ZnifferProtocolDataRate.ZWave_100k:
case ZnifferProtocolDataRate.LongRange_100k:
return "100 kbit/s";
}
}
return `Unknown (${num2hex(rate)})`;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/consts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export const MAX_NODES_LR = 4000; // FIXME: This seems too even, figure out the
/** The broadcast target node id */
export const NODE_ID_BROADCAST = 0xff;

/** The broadcast target node id for Z-Wave LR */
export const NODE_ID_BROADCAST_LR = 0xfff;

/** The highest allowed node id */
export const NODE_ID_MAX = MAX_NODES;

Expand Down
56 changes: 49 additions & 7 deletions packages/zwave-js/src/lib/zniffer/MPDU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
MPDUHeaderType,
type MessageOrCCLogEntry,
type MessageRecord,
NODE_ID_BROADCAST,
NODE_ID_BROADCAST_LR,
Protocols,
type RSSI,
ZWaveError,
Expand Down Expand Up @@ -906,6 +908,7 @@ export class BeamStop {
}
}

/** An application-oriented representation of a Z-Wave frame that was captured by the Zniffer */
export type ZWaveFrame =
// Common fields for all Z-Wave frames
& {
Expand Down Expand Up @@ -965,6 +968,14 @@ export type ZWaveFrame =
)
>
)
// Broadcast frame. This is technically a singlecast frame,
// but the destination node ID is always 255 and it is not routed
| {
type: ZWaveFrameType.Broadcast;
destinationNodeId: typeof NODE_ID_BROADCAST;
ackRequested: boolean;
payload: Buffer | CommandClass;
}
| {
// Multicast frame, not routed
type: ZWaveFrameType.Multicast;
Expand Down Expand Up @@ -1025,12 +1036,21 @@ export type LongRangeFrame =
}
// Different kinds of Long Range frames:
& (
{
| {
// Singlecast frame
type: LongRangeFrameType.Singlecast;
ackRequested: boolean;
payload: Buffer | CommandClass;
} | {
}
| {
// Broadcast frame. This is technically a singlecast frame,
// but the destination node ID is always 4095
type: LongRangeFrameType.Broadcast;
destinationNodeId: typeof NODE_ID_BROADCAST_LR;
ackRequested: boolean;
payload: Buffer | CommandClass;
}
| {
// Acknowledgement frame
type: LongRangeFrameType.Ack;
incomingRSSI: RSSI;
Expand Down Expand Up @@ -1136,13 +1156,24 @@ export function mpduToZWaveFrame(
};

if (mpdu instanceof SinglecastZWaveMPDU) {
return {
type: ZWaveFrameType.Singlecast,
const ret = {
...retBase,
destinationNodeId: mpdu.destinationNodeId,
ackRequested: mpdu.ackRequested,
payload: payloadCC ?? mpdu.payload,
};
if (mpdu.destinationNodeId === NODE_ID_BROADCAST) {
return {
type: ZWaveFrameType.Broadcast,
destinationNodeId: mpdu.destinationNodeId,
...ret,
};
} else {
return {
type: ZWaveFrameType.Singlecast,
destinationNodeId: mpdu.destinationNodeId,
...ret,
};
}
} else if (mpdu instanceof AckZWaveMPDU) {
return {
type: ZWaveFrameType.AckDirect,
Expand Down Expand Up @@ -1235,12 +1266,23 @@ export function mpduToLongRangeFrame(
};

if (mpdu instanceof SinglecastLongRangeMPDU) {
return {
const ret = {
...retBase,
type: LongRangeFrameType.Singlecast,
ackRequested: mpdu.ackRequested,
payload: payloadCC ?? mpdu.payload,
};
if (mpdu.destinationNodeId === NODE_ID_BROADCAST_LR) {
return {
type: LongRangeFrameType.Broadcast,
...ret,
destinationNodeId: mpdu.destinationNodeId, // Make TS happy
};
} else {
return {
type: LongRangeFrameType.Singlecast,
...ret,
};
}
} else if (mpdu instanceof AckLongRangeMPDU) {
return {
type: LongRangeFrameType.Ack,
Expand Down
9 changes: 9 additions & 0 deletions packages/zwave-js/src/lib/zniffer/Zniffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export interface ZnifferOptions {
* Supported regions and their names have to be queried using the `getFrequencies` and `getFrequencyInfo(frequency)` commands.
*/
defaultFrequency?: number;

/** Limit the number of frames that are kept in memory. */
maxCapturedFrames?: number;
}

function is700PlusSeries(
Expand Down Expand Up @@ -399,6 +402,12 @@ export class Zniffer extends TypedEventEmitter<ZnifferEventCallbacks> {
frameData: dataMsg.payload,
};
this._capturedFrames.push(capture);
if (
this._options.maxCapturedFrames != undefined
&& this._capturedFrames.length > this._options.maxCapturedFrames
) {
this._capturedFrames.shift();
}
this.handleDataMessage(dataMsg, capture);
}
}
Expand Down
4 changes: 2 additions & 2 deletions packages/zwave-js/src/lib/zniffer/_Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ export enum ZWaveFrameType {
ExplorerInclusionRequest,
BeamStart,
BeamStop,
Broadcast,
}

/** An application-oriented representation of a Z-Wave frame that was captured by the Zniffer */

export enum LongRangeFrameType {
Singlecast,
Ack,
BeamStart,
BeamStop,
Broadcast,
}

0 comments on commit fcae050

Please sign in to comment.