zigbee-herdsman
Version:
An open source ZigBee gateway solution with node.js.
95 lines (85 loc) • 3.68 kB
text/typescript
import type * as Zcl from "../../zspec/zcl";
import type {SendPolicy} from "../tstype";
// biome-ignore lint/suspicious/noExplicitAny: API
export class Request<Type = any> {
static defaultSendPolicy: {[key: number]: SendPolicy} = {
0: "keep-payload", // Read Attributes
1: "immediate", // Read Attributes Response
2: "keep-command", // Write Attributes
3: "keep-cmd-undiv", // Write Attributes Undivided
4: "immediate", // Write Attributes Response
5: "keep-command", // Write Attributes No Response
6: "keep-payload", // Configure Reporting
7: "immediate", // Configure Reporting Response
8: "keep-payload", // Read Reporting Configuration
9: "immediate", // Read Reporting Configuration Response
10: "keep-payload", // Report attributes
11: "immediate", // Default Response
12: "keep-payload", // Discover Attributes
13: "immediate", // Discover Attributes Response
14: "keep-payload", // Read Attributes Structured
15: "keep-payload", // Write Attributes Structured
16: "immediate", // Write Attributes Structured response
17: "keep-payload", // Discover Commands Received
18: "immediate", // Discover Commands Received Response
19: "keep-payload", // Discover Commands Generated
20: "immediate", // Discover Commands Generated Response
21: "keep-payload", // Discover Attributes Extended
22: "immediate", // Discover Attributes Extended Response
};
private func: (frame: Zcl.Frame) => Promise<Type>;
frame: Zcl.Frame;
expires: number;
sendPolicy: SendPolicy | undefined;
private resolveQueue: Array<(value: Type) => void>;
private rejectQueue: Array<(error: Error) => void>;
private lastError: Error;
constructor(
func: (frame: Zcl.Frame) => Promise<Type>,
frame: Zcl.Frame,
timeout: number,
sendPolicy?: SendPolicy,
lastError?: Error,
resolve?: (value: Type) => void,
reject?: (error: Error) => void,
) {
this.func = func;
this.frame = frame;
this.expires = timeout + Date.now();
this.sendPolicy = sendPolicy ?? (!frame.command ? undefined : Request.defaultSendPolicy[frame.command.ID]);
this.resolveQueue = resolve === undefined ? new Array<(value: Type) => void>() : new Array<(value: Type) => void>(resolve);
this.rejectQueue = reject === undefined ? new Array<(error: Error) => void>() : new Array<(error: Error) => void>(reject);
this.lastError = lastError ?? Error("Request rejected before first send");
}
moveCallbacks(from: Request<Type>): void {
this.resolveQueue = this.resolveQueue.concat(from.resolveQueue);
this.rejectQueue = this.rejectQueue.concat(from.rejectQueue);
from.resolveQueue.length = 0;
from.rejectQueue.length = 0;
}
addCallbacks(resolve: (value: Type) => void, reject: (error: Error) => void): void {
this.resolveQueue.push(resolve);
this.rejectQueue.push(reject);
}
reject(error?: Error): void {
for (const el of this.rejectQueue) {
el(error ?? this.lastError);
}
this.rejectQueue.length = 0;
}
resolve(value: Type): void {
for (const el of this.resolveQueue) {
el(value);
}
this.resolveQueue.length = 0;
}
async send(): Promise<Type> {
try {
return await this.func(this.frame);
} catch (error) {
this.lastError = error as Error;
throw error;
}
}
}
export default Request;