Skip to content

Commit

Permalink
fix: convert LR beam TX power, documentation for beam frames
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone committed May 8, 2024
1 parent 0cc41d4 commit f0693a5
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 43 deletions.
4 changes: 0 additions & 4 deletions docs/api/config-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,6 @@ interface GenericDeviceClass {
readonly key: number;
readonly label: string;
readonly requiresSecurity?: boolean;
readonly supportedCCs: readonly CommandClasses[];
readonly controlledCCs: readonly CommandClasses[];
readonly maySupportBasicCC: boolean;
readonly specific: ReadonlyMap<number, SpecificDeviceClass>;
}
Expand All @@ -428,8 +426,6 @@ interface SpecificDeviceClass {
readonly label: string;
readonly zwavePlusDeviceType?: string;
readonly requiresSecurity?: boolean;
readonly supportedCCs: readonly CommandClasses[];
readonly controlledCCs: readonly CommandClasses[];
readonly maySupportBasicCC: boolean;
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/api/controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ interface LifelineRoutes {
```ts
interface RouteStatistics {
/** The protocol and used data rate for this route */
protocolDataRate: ProtocolDataRate;
protocolDataRate?: ProtocolDataRate;
/** Which nodes are repeaters for this route */
repeaters: number[];

Expand Down
10 changes: 2 additions & 8 deletions docs/api/node.md
Original file line number Diff line number Diff line change
Expand Up @@ -884,8 +884,6 @@ interface DeviceClass {
readonly basic: BasicDeviceClass;
readonly generic: GenericDeviceClass;
readonly specific: SpecificDeviceClass;
readonly mandatorySupportedCCs: readonly CommandClasses[];
readonly mandatoryControlledCCs: readonly CommandClasses[];
}
```

Expand All @@ -905,8 +903,6 @@ interface GenericDeviceClass {
readonly key: number;
readonly label: string;
readonly requiresSecurity?: boolean;
readonly supportedCCs: readonly CommandClasses[];
readonly controlledCCs: readonly CommandClasses[];
readonly maySupportBasicCC: boolean;
readonly specific: ReadonlyMap<number, SpecificDeviceClass>;
}
Expand All @@ -920,8 +916,6 @@ interface SpecificDeviceClass {
readonly label: string;
readonly zwavePlusDeviceType?: string;
readonly requiresSecurity?: boolean;
readonly supportedCCs: readonly CommandClasses[];
readonly controlledCCs: readonly CommandClasses[];
readonly maySupportBasicCC: boolean;
}
```
Expand All @@ -946,7 +940,7 @@ If the `Z-Wave+` Command Class is supported, this returns the `Z-Wave+` node typ

```ts
enum ZWavePlusNodeType {
Node = 0,
Node = 0, // ZWave+ Node
IPGateway = 2,
}
```
Expand Down Expand Up @@ -1559,7 +1553,7 @@ interface NodeStatistics {
```ts
interface RouteStatistics {
/** The protocol and used data rate for this route */
protocolDataRate: ProtocolDataRate;
protocolDataRate?: ProtocolDataRate;
/** Which nodes are repeaters for this route */
repeaters: number[];

Expand Down
64 changes: 61 additions & 3 deletions docs/api/zniffer.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,15 +153,18 @@ type CorruptedFrame = {
};
```

A valid frame can either be a Z-Wave frame or a Z-Wave Long Range frame...
A valid frame can either be a Z-Wave frame or a Z-Wave Long Range frame, either normal or beaming...

<!-- #import Frame from "zwave-js" -->

```ts
type Frame = ZWaveFrame | LongRangeFrame;
type Frame =
| ZWaveFrame
| LongRangeFrame
| BeamFrame;
```

...both of which have several subtypes:
...all of which have several subtypes:

<!-- #import ZWaveFrame from "zwave-js" -->

Expand Down Expand Up @@ -302,6 +305,57 @@ type LongRangeFrame =
);
```

<!-- #import BeamFrame from "zwave-js" -->

```ts
type BeamFrame =
// Common fields for all Beam frames
& {
channel: number;
}
// Different types of beam frames:
& (
| {
// Z-Wave Classic
protocol: Protocols.ZWave;
type: ZWaveFrameType.BeamStart;

protocolDataRate: ZnifferProtocolDataRate;
rssiRaw: number;
rssi?: RSSI;
region: ZnifferRegion;

homeIdHash?: number;
destinationNodeId: number;
}
| {
// Z-Wave Long Range
protocol: Protocols.ZWaveLongRange;
type: LongRangeFrameType.BeamStart;

protocolDataRate: ZnifferProtocolDataRate;
rssiRaw: number;
rssi?: RSSI;
region: ZnifferRegion;

txPower: number;
homeIdHash: number;
destinationNodeId: number;
}
// The Zniffer sends the same command for the beam ending for both
// Z-Wave Classic and Long Range. To make testing the frame type more
// consistent with the other frames, two different values are used
| {
protocol: Protocols.ZWave;
type: ZWaveFrameType.BeamStop;
}
| {
protocol: Protocols.ZWaveLongRange;
type: LongRangeFrameType.BeamStop;
}
);
```

## Type definitions

<!-- #import Protocols from "@zwave-js/core" -->
Expand All @@ -323,6 +377,8 @@ enum ZWaveFrameType {
ExplorerNormal,
ExplorerSearchResult,
ExplorerInclusionRequest,
BeamStart,
BeamStop,
}
```

Expand All @@ -332,6 +388,8 @@ enum ZWaveFrameType {
enum LongRangeFrameType {
Singlecast,
Ack,
BeamStart,
BeamStop,
}
```

Expand Down
20 changes: 0 additions & 20 deletions packages/serial/src/message/ZnifferMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ export class ZnifferMessage {
// The ZnifferParser takes care of segmenting frames, so here we
// only cut off the type byte from the payload
this.payload = payload.subarray(1);
// // TODO: Having the header etc. be part of the payload is a bit awkward
// const length = payload[9];
// this.payload = payload.subarray(1, 10 + length);
} else {
throw new ZWaveError(
`Invalid Zniffer message type ${this.type as any}`,
Expand Down Expand Up @@ -166,23 +163,6 @@ export class ZnifferMessage {
const ret = new Constructor(options);
return ret;
}

// /** Generates a representation of this Message for the log */
// public toLogEntry(): MessageOrCCLogEntry {
// const tags = [
// this.type === MessageType.Request ? "REQ" : "RES",
// FunctionType[this.functionType],
// ];
// const nodeId = this.getNodeId();
// if (nodeId) tags.unshift(getNodeTag(nodeId));

// return {
// tags,
// message: this.payload.length > 0
// ? { payload: `0x${this.payload.toString("hex")}` }
// : undefined,
// };
// }
}

function computeChecksumXOR(buffer: Buffer): number {
Expand Down
1 change: 1 addition & 0 deletions packages/zwave-js/src/Zniffer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type { MPDU } from "./lib/zniffer/MPDU";
export type {
BeamFrame,
CorruptedFrame,
Frame,
LongRangeFrame,
Expand Down
35 changes: 28 additions & 7 deletions packages/zwave-js/src/lib/zniffer/MPDU.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,27 @@ function getChannelConfiguration(region: ZnifferRegion): "1/2" | "3" | "4" {
}
}

function longRangeBeamPowerToDBm(power: number): number {
return [
-6,
-2,
2,
6,
10,
13,
16,
19,
21,
23,
25,
26,
27,
28,
29,
30,
][power];
}

function formatNodeId(nodeId: number): string {
return padStart(nodeId.toString(), 3, "0");
}
Expand Down Expand Up @@ -858,7 +879,8 @@ export class LongRangeBeamStart {
}
}

this.txPower = data[1] >>> 4;
const txPower = data[1] >>> 4;
this.txPower = longRangeBeamPowerToDBm(txPower);
this.destinationNodeId = data.readUint16BE(1) & 0x0fff;
this.homeIdHash = data[3];
}
Expand All @@ -878,8 +900,7 @@ export class LongRangeBeamStart {
"protocol/data rate": znifferProtocolDataRateToString(
this.frameInfo.protocolDataRate,
),
// FIXME: convert to dBm
"TX power": `${this.txPower}`,
"TX power": `${this.txPower} dBm`,
RSSI: this.frameInfo.rssi != undefined
? rssiToString(this.frameInfo.rssi)
: this.frameInfo.rssiRaw.toString(),
Expand Down Expand Up @@ -1067,8 +1088,6 @@ export type BeamFrame =
// Common fields for all Beam frames
& {
channel: number;
// Although it is being parsed, Stop frames contain no
// valid data for everything but the channel no.
}
// Different types of beam frames:
& (
Expand All @@ -1086,6 +1105,7 @@ export type BeamFrame =
destinationNodeId: number;
}
| {
// Z-Wave Long Range
protocol: Protocols.ZWaveLongRange;
type: LongRangeFrameType.BeamStart;

Expand All @@ -1098,8 +1118,9 @@ export type BeamFrame =
homeIdHash: number;
destinationNodeId: number;
}
// Currently, these two are identical, but we distinguish them
// to make the Frame type more consistent
// The Zniffer sends the same command for the beam ending for both
// Z-Wave Classic and Long Range. To make testing the frame type more
// consistent with the other frames, two different values are used
| {
protocol: Protocols.ZWave;
type: ZWaveFrameType.BeamStop;
Expand Down

0 comments on commit f0693a5

Please sign in to comment.