Skip to content

Commit

Permalink
refactor: decouple Serial API Message parsing and creation (#7306)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored Oct 23, 2024
1 parent 62e6cfd commit 7db7887
Show file tree
Hide file tree
Showing 82 changed files with 5,235 additions and 3,205 deletions.
3 changes: 0 additions & 3 deletions packages/cc/src/cc/LanguageCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,11 @@ export class LanguageCCReport extends LanguageCC {
options: WithAddress<LanguageCCReportOptions>,
) {
super(options);

// TODO: Check implementation:
this.language = options.language;
this.country = options.country;
}

public static from(raw: CCRaw, ctx: CCParsingContext): LanguageCCReport {
// if (gotDeserializationOptions(options)) {
validatePayload(raw.payload.length >= 3);
const language = raw.payload.toString("ascii", 0, 3);
let country: MaybeNotKnown<string>;
Expand Down
12 changes: 0 additions & 12 deletions packages/cc/src/cc/NoOperationCC.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { CommandClasses, MessagePriority } from "@zwave-js/core/safe";
import type { Message } from "@zwave-js/serial";
import { PhysicalCCAPI } from "../lib/API";
import { CommandClass } from "../lib/CommandClass";
import {
API,
commandClass,
implementedVersion,
} from "../lib/CommandClassDecorators";
import { isCommandClassContainer } from "../lib/ICommandClassContainer";

// @noSetValueAPI This CC has no set-type commands
// @noInterview There's nothing to interview here
Expand Down Expand Up @@ -37,13 +35,3 @@ export class NoOperationCCAPI extends PhysicalCCAPI {
export class NoOperationCC extends CommandClass {
declare ccCommand: undefined;
}

/**
* @publicAPI
* Tests if a given message is a ping
*/
export function messageIsPing<T extends Message>(
msg: T,
): msg is T & { command: NoOperationCC } {
return isCommandClassContainer(msg) && msg.command instanceof NoOperationCC;
}
1 change: 1 addition & 0 deletions packages/cc/src/cc/NotificationCC.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,7 @@ export class NotificationCCReport extends NotificationCC {
// Convert CommandClass instances to a standardized object representation
const cc = CommandClass.parse(this.eventParameters, {
...ctx,
frameType: "singlecast",
sourceNodeId: this.nodeId as number,
// Security encapsulation is handled outside of this CC,
// so it is not needed here:
Expand Down
2 changes: 1 addition & 1 deletion packages/cc/src/cc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ export {
MultilevelSwitchCCSupportedReport,
MultilevelSwitchCCValues,
} from "./MultilevelSwitchCC";
export { NoOperationCC, messageIsPing } from "./NoOperationCC";
export { NoOperationCC } from "./NoOperationCC";
export type {
NodeNamingAndLocationCCLocationReportOptions,
NodeNamingAndLocationCCLocationSetOptions,
Expand Down
1 change: 0 additions & 1 deletion packages/cc/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export * from "./lib/API";
export * from "./lib/CommandClass";
export * from "./lib/CommandClassDecorators";
export * from "./lib/EncapsulatingCommandClass";
export * from "./lib/ICommandClassContainer";
export {
MGRPExtension,
MOSExtension,
Expand Down
37 changes: 2 additions & 35 deletions packages/cc/src/lib/CommandClass.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,6 @@ import {
isEncapsulatingCommandClass,
isMultiEncapsulatingCommandClass,
} from "./EncapsulatingCommandClass";
import {
type ICommandClassContainer,
isCommandClassContainer,
} from "./ICommandClassContainer";
import {
type CCValue,
type DynamicCCValue,
Expand Down Expand Up @@ -195,15 +191,6 @@ export class CCRaw {
public withPayload(payload: Buffer): CCRaw {
return new CCRaw(this.ccId, this.ccCommand, payload);
}

public serialize(): Buffer {
const ccIdLength = this.ccId >= 0xf100 ? 2 : 1;
const data = Buffer.allocUnsafe(ccIdLength + 1 + this.payload.length);
data.writeUIntBE(this.ccId, 0, ccIdLength);
data[ccIdLength] = this.ccCommand ?? 0;
this.payload.copy(data, ccIdLength + 1);
return data;
}
}

// @publicAPI
Expand All @@ -226,10 +213,10 @@ export class CommandClass implements CCId {
}

public static parse(
payload: Buffer,
data: Buffer,
ctx: CCParsingContext,
): CommandClass {
const raw = CCRaw.parse(payload);
const raw = CCRaw.parse(data);

// Find the correct subclass constructor to invoke
const CCConstructor = getCCConstructor(raw.ccId);
Expand Down Expand Up @@ -1189,26 +1176,6 @@ export class InvalidCC extends CommandClass {
}
}

/** @publicAPI */
export function assertValidCCs(container: ICommandClassContainer): void {
if (container.command instanceof InvalidCC) {
if (typeof container.command.reason === "number") {
throw new ZWaveError(
"The message payload failed validation!",
container.command.reason,
);
} else {
throw new ZWaveError(
"The message payload is invalid!",
ZWaveErrorCodes.PacketFormat_InvalidPayload,
container.command.reason,
);
}
} else if (isCommandClassContainer(container.command)) {
assertValidCCs(container.command);
}
}

export type CCConstructor<T extends CommandClass> = typeof CommandClass & {
// I don't like the any, but we need it to support half-implemented CCs (e.g. report classes)
new (options: any): T;
Expand Down
14 changes: 0 additions & 14 deletions packages/cc/src/lib/ICommandClassContainer.ts
Original file line number Diff line number Diff line change
@@ -1,14 +0,0 @@
import { CommandClass } from "./CommandClass";

export interface ICommandClassContainer {
command: CommandClass;
}

/**
* Tests if the given message contains a CC
*/
export function isCommandClassContainer<T>(
msg: T | undefined,
): msg is T & ICommandClassContainer {
return (msg as any)?.command instanceof CommandClass;
}
2 changes: 0 additions & 2 deletions packages/core/src/consts/Transmission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ export function routingSchemeToString(scheme: RoutingScheme): string {
export interface TXReport {
/** Transmission time in ticks (multiples of 10ms) */
txTicks: number;
/** Number of repeaters used in the route to the destination, 0 for direct range */
numRepeaters: number;
/** RSSI value of the acknowledgement frame */
ackRSSI?: RSSI;
/** RSSI values of the incoming acknowledgement frame, measured by repeater 0...3 */
Expand Down
12 changes: 1 addition & 11 deletions packages/host/src/ZWaveHost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,6 @@ export interface HostIDs {
homeId: number;
}

// FIXME: This should not be needed. Instead have the driver set callback IDs during sendMessage
/** Allows generating a new callback ID */
export interface GetNextCallbackId {
/**
* Returns the next callback ID. Callback IDs are used to correlate requests
* to the controller/nodes with its response
*/
getNextCallbackId(): number;
}

/** Allows querying device configuration for a node */
export interface GetDeviceConfig {
getDeviceConfig(nodeId: number): DeviceConfig | undefined;
Expand Down Expand Up @@ -71,7 +61,7 @@ export interface CCParsingContext
__internalIsMockNode?: boolean;

/** If known, the frame type of the containing message */
frameType?: FrameType;
frameType: FrameType;

getHighestSecurityClass(nodeId: number): MaybeNotKnown<SecurityClass>;

Expand Down
5 changes: 2 additions & 3 deletions packages/maintenance/src/generateTypedDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,9 +359,8 @@ async function processCCDocFile(
if (!APIClass) return;

const ccId = getCommandClassFromClassDeclaration(
// FIXME: there seems to be some discrepancy between ts-morph's bundled typescript and our typescript
file.compilerNode as any,
APIClass.compilerNode as any,
file.compilerNode,
APIClass.compilerNode,
);
if (ccId == undefined) return;
const ccName = getCCName(ccId);
Expand Down
Loading

0 comments on commit 7db7887

Please sign in to comment.