UNPKG

inventoresed

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

226 lines (203 loc) 7.03 kB
import { encodeBitMask, MAX_NODES, MessagePriority, NodeType, NUM_NODEMASK_BYTES, } from "@zwave-js/core"; import type { ZWaveHost } from "@zwave-js/host"; import { expectedResponse, FunctionType, gotDeserializationOptions, Message, MessageBaseOptions, MessageDeserializationOptions, MessageType, messageTypes, priority, } from "@zwave-js/serial"; import { parseNodeBitMask } from "../../controller/NodeBitMask"; import { getChipTypeAndVersion, getZWaveChipType, UnknownZWaveChipType, } from "../../controller/ZWaveChipTypes"; import type { ZWaveApiVersion } from "../_Types"; @messageTypes(MessageType.Request, FunctionType.GetSerialApiInitData) @expectedResponse(FunctionType.GetSerialApiInitData) @priority(MessagePriority.Controller) export class GetSerialApiInitDataRequest extends Message {} export interface GetSerialApiInitDataResponseOptions extends MessageBaseOptions { zwaveApiVersion: ZWaveApiVersion; isPrimary: boolean; nodeType: NodeType; supportsTimers: boolean; isSIS: boolean; nodeIds: number[]; zwaveChipType?: string | UnknownZWaveChipType; } @messageTypes(MessageType.Response, FunctionType.GetSerialApiInitData) export class GetSerialApiInitDataResponse extends Message { public constructor( host: ZWaveHost, options: | MessageDeserializationOptions | GetSerialApiInitDataResponseOptions, ) { super(host, options); if (gotDeserializationOptions(options)) { const apiVersion = this.payload[0]; if (apiVersion < 10) { this.zwaveApiVersion = { kind: "legacy", version: apiVersion, }; } else { // this module uses the officially specified Host API this.zwaveApiVersion = { kind: "official", version: apiVersion - 9, }; } const capabilities = this.payload[1]; if (this.zwaveApiVersion.kind === "official") { // The new "official" Host API specs sneakily switched the meaning of some flags this.nodeType = capabilities & 0b0001 ? NodeType.Controller : NodeType["End Node"]; this.supportsTimers = !!(capabilities & 0b0010); this.isPrimary = !!(capabilities & 0b0100); this.isSIS = !!(capabilities & 0b1000); } else { this.nodeType = capabilities & 0b0001 ? NodeType["End Node"] : NodeType.Controller; this.supportsTimers = !!(capabilities & 0b0010); this.isPrimary = !(capabilities & 0b0100); this.isSIS = !!(capabilities & 0b1000); } let offset = 2; this.nodeIds = []; if (this.payload.length > offset) { const nodeListLength = this.payload[offset]; // Controller Nodes MUST set this field to 29 if ( nodeListLength === NUM_NODEMASK_BYTES && this.payload.length >= offset + 1 + nodeListLength ) { const nodeBitMask = this.payload.slice( offset + 1, offset + 1 + nodeListLength, ); this.nodeIds = parseNodeBitMask(nodeBitMask); } offset += 1 + nodeListLength; } // these might not be present: const chipType = this.payload[offset]; const chipVersion = this.payload[offset + 1]; if (chipType != undefined && chipVersion != undefined) { this.zwaveChipType = getZWaveChipType(chipType, chipVersion); } } else { this.zwaveApiVersion = options.zwaveApiVersion; this.isPrimary = options.isPrimary; this.nodeType = options.nodeType; this.supportsTimers = options.supportsTimers; this.isSIS = options.isSIS; this.nodeIds = options.nodeIds; this.zwaveChipType = options.zwaveChipType; } } public zwaveApiVersion: ZWaveApiVersion; public isPrimary: boolean; public nodeType: NodeType; public supportsTimers: boolean; public isSIS: boolean; public nodeIds: readonly number[]; public zwaveChipType?: string | UnknownZWaveChipType; public serialize(): Buffer { let chipType: UnknownZWaveChipType | undefined; if (typeof this.zwaveChipType === "string") { chipType = getChipTypeAndVersion(this.zwaveChipType); } else { chipType = this.zwaveChipType; } this.payload = Buffer.allocUnsafe( 3 + NUM_NODEMASK_BYTES + (chipType ? 2 : 0), ); let capabilities = 0; if (this.supportsTimers) capabilities |= 0b0010; if (this.isSIS) capabilities |= 0b1000; if (this.zwaveApiVersion.kind === "legacy") { this.payload[0] = this.zwaveApiVersion.version; if (this.nodeType === NodeType["End Node"]) capabilities |= 0b0001; if (!this.isPrimary) capabilities |= 0b0100; } else { this.payload[0] = this.zwaveApiVersion.version + 9; if (this.nodeType === NodeType.Controller) capabilities |= 0b0001; if (this.isPrimary) capabilities |= 0b0100; } this.payload[1] = capabilities; this.payload[2] = NUM_NODEMASK_BYTES; const nodeBitMask = encodeBitMask(this.nodeIds, MAX_NODES); nodeBitMask.copy(this.payload, 3); if (chipType) { this.payload[3 + NUM_NODEMASK_BYTES] = chipType.type; this.payload[3 + NUM_NODEMASK_BYTES + 1] = chipType.version; } return super.serialize(); } // public toLogEntry(): MessageOrCCLogEntry { // const message: MessageRecord = { // "Z-Wave API Version": `${this.zwaveApiVersion.version} (${this.zwaveApiVersion.kind})`, // "node type": getEnumMemberName(NodeType, this.nodeType), // role: this.isPrimary ? "primary" : "secondary", // "is SIS": this.isSIS, // "supports timers": this.supportsTimers, // }; // if (this.zwaveChipType) { // message["Z-Wave chip type"] = // typeof this.zwaveChipType === "string" // ? this.zwaveChipType // : `unknown (type = ${num2hex( // this.zwaveChipType.type, // )}, version = ${num2hex(this.zwaveChipType.version)})`; // } // return { // ...super.toLogEntry(), // message, // }; // } } // Z-Stick 7, 7.15 // 12:15:28.505 DRIVER « [RES] [GetSerialApiInitData] // Z-Wave API Version: 9 (proprietary) // node type: controller // supports timers: false // is secondary: false // is SUC: true // chip type: 7 // chip version: 0 // ACC-UZB3 // 12:21:11.141 DRIVER « [RES] [GetSerialApiInitData] // Z-Wave API Version: 8 (proprietary) // node type: controller // supports timers: false // is secondary: false // is SUC: true // chip type: 5 // chip version: 0 // UZB7, 7.11 // 12:33:14.211 DRIVER « [RES] [GetSerialApiInitData] // Z-Wave API Version: 8 (proprietary) // node type: controller // supports timers: false // is secondary: false // is SUC: true // chip type: 7 // chip version: 0