inventoresed
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
226 lines (203 loc) • 7.03 kB
text/typescript
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";
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;
}
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