diff --git a/packages/zwave-js/src/lib/controller/Controller.ts b/packages/zwave-js/src/lib/controller/Controller.ts index 3a38222db524..18e3a3f155c8 100644 --- a/packages/zwave-js/src/lib/controller/Controller.ts +++ b/packages/zwave-js/src/lib/controller/Controller.ts @@ -143,6 +143,10 @@ import { GetControllerVersionRequest, type GetControllerVersionResponse, } from "../serialapi/capability/GetControllerVersionMessages"; +import { + GetLongRangeNodesRequest, + type GetLongRangeNodesResponse, +} from "../serialapi/capability/GetLongRangeNodesMessages"; import { GetProtocolVersionRequest, type GetProtocolVersionResponse, @@ -152,8 +156,6 @@ import { type GetSerialApiCapabilitiesResponse, } from "../serialapi/capability/GetSerialApiCapabilitiesMessages"; import { - GetLongRangeNodesRequest, - type GetLongRangeNodesResponse, GetSerialApiInitDataRequest, type GetSerialApiInitDataResponse, } from "../serialapi/capability/GetSerialApiInitDataMessages"; @@ -1547,8 +1549,7 @@ export class ZWaveController const nodeIds: number[] = []; if (this.supportsLongRange) { - const segment = 0; - while (true) { + for (let segment = 0;; segment++) { const nodesResponse = await this.driver.sendMessage< GetLongRangeNodesResponse >( @@ -1557,9 +1558,8 @@ export class ZWaveController }), ); nodeIds.push(...nodesResponse.nodeIds); - if (!nodesResponse.moreNodes) { - break; - } + + if (!nodesResponse.moreNodes) break; } } return nodeIds; diff --git a/packages/zwave-js/src/lib/serialapi/capability/GetLongRangeNodesMessages.ts b/packages/zwave-js/src/lib/serialapi/capability/GetLongRangeNodesMessages.ts new file mode 100644 index 000000000000..dbbe9b26d0c1 --- /dev/null +++ b/packages/zwave-js/src/lib/serialapi/capability/GetLongRangeNodesMessages.ts @@ -0,0 +1,119 @@ +import { + MessagePriority, + NUM_LR_NODEMASK_SEGMENT_BYTES, + NUM_LR_NODES_PER_SEGMENT, + encodeLongRangeNodeBitMask, + parseLongRangeNodeBitMask, +} from "@zwave-js/core"; +import type { ZWaveHost } from "@zwave-js/host"; +import { + FunctionType, + Message, + type MessageBaseOptions, + type MessageDeserializationOptions, + MessageType, + expectedResponse, + gotDeserializationOptions, + messageTypes, + priority, +} from "@zwave-js/serial"; + +export interface GetLongRangeNodesRequestOptions extends MessageBaseOptions { + segmentNumber: number; +} + +@messageTypes(MessageType.Request, FunctionType.GetLongRangeNodes) +@expectedResponse(FunctionType.GetLongRangeNodes) +@priority(MessagePriority.Controller) +export class GetLongRangeNodesRequest extends Message { + public constructor( + host: ZWaveHost, + options: + | MessageDeserializationOptions + | GetLongRangeNodesRequestOptions, + ) { + super(host, options); + + if (gotDeserializationOptions(options)) { + this.segmentNumber = this.payload[0]; + } else { + this.segmentNumber = options.segmentNumber; + } + } + + public segmentNumber: number; + + public serialize(): Buffer { + this.payload = Buffer.from([this.segmentNumber]); + return super.serialize(); + } +} + +export interface GetLongRangeNodesResponseOptions extends MessageBaseOptions { + moreNodes: boolean; + segmentNumber: number; + nodeIds: number[]; +} + +@messageTypes(MessageType.Response, FunctionType.GetLongRangeNodes) +export class GetLongRangeNodesResponse extends Message { + public constructor( + host: ZWaveHost, + options: + | MessageDeserializationOptions + | GetLongRangeNodesResponseOptions, + ) { + super(host, options); + + if (gotDeserializationOptions(options)) { + this.moreNodes = this.payload[0] != 0; + this.segmentNumber = this.payload[1]; + const listLength = this.payload[2]; + + const listStart = 3; + const listEnd = listStart + listLength; + if (listEnd <= this.payload.length) { + const nodeBitMask = this.payload.subarray( + listStart, + listEnd, + ); + this.nodeIds = parseLongRangeNodeBitMask( + nodeBitMask, + this.listStartNode(), + ); + } else { + this.nodeIds = []; + } + } else { + this.moreNodes = options.moreNodes; + this.segmentNumber = options.segmentNumber; + this.nodeIds = options.nodeIds; + } + } + + public moreNodes: boolean; + public segmentNumber: number; + public nodeIds: readonly number[]; + + public serialize(): Buffer { + this.payload = Buffer.allocUnsafe( + 3 + NUM_LR_NODEMASK_SEGMENT_BYTES, + ); + + this.payload[0] = this.moreNodes ? 1 : 0; + this.payload[1] = this.segmentNumber; + this.payload[2] = NUM_LR_NODEMASK_SEGMENT_BYTES; + + const nodeBitMask = encodeLongRangeNodeBitMask( + this.nodeIds, + this.listStartNode(), + ); + nodeBitMask.copy(this.payload, 3); + + return super.serialize(); + } + + private listStartNode(): number { + return 256 + NUM_LR_NODES_PER_SEGMENT * this.segmentNumber; + } +} diff --git a/packages/zwave-js/src/lib/serialapi/capability/GetSerialApiInitDataMessages.ts b/packages/zwave-js/src/lib/serialapi/capability/GetSerialApiInitDataMessages.ts index e018978b0b63..b0613533f78e 100644 --- a/packages/zwave-js/src/lib/serialapi/capability/GetSerialApiInitDataMessages.ts +++ b/packages/zwave-js/src/lib/serialapi/capability/GetSerialApiInitDataMessages.ts @@ -1,13 +1,9 @@ import { MAX_NODES, MessagePriority, - NUM_LR_NODEMASK_SEGMENT_BYTES, - NUM_LR_NODES_PER_SEGMENT, NUM_NODEMASK_BYTES, NodeType, encodeBitMask, - encodeLongRangeNodeBitMask, - parseLongRangeNodeBitMask, parseNodeBitMask, } from "@zwave-js/core"; import type { ZWaveHost } from "@zwave-js/host"; @@ -219,104 +215,3 @@ export class GetSerialApiInitDataResponse extends Message { // is SUC: true // chip type: 7 // chip version: 0 - -// FIXME: Move these into their own file -export interface GetLongRangeNodesRequestOptions extends MessageBaseOptions { - segmentNumber: number; -} - -@messageTypes(MessageType.Request, FunctionType.GetLongRangeNodes) -@expectedResponse(FunctionType.GetLongRangeNodes) -@priority(MessagePriority.Controller) -export class GetLongRangeNodesRequest extends Message { - public constructor( - host: ZWaveHost, - options: - | MessageDeserializationOptions - | GetLongRangeNodesRequestOptions, - ) { - super(host, options); - - if (gotDeserializationOptions(options)) { - this.segmentNumber = this.payload[0]; - } else { - this.segmentNumber = options.segmentNumber; - } - } - - public segmentNumber: number; - - public serialize(): Buffer { - this.payload = Buffer.from([this.segmentNumber]); - return super.serialize(); - } -} - -export interface GetLongRangeNodesResponseOptions extends MessageBaseOptions { - moreNodes: boolean; - segmentNumber: number; - nodeIds: number[]; -} - -@messageTypes(MessageType.Response, FunctionType.GetLongRangeNodes) -export class GetLongRangeNodesResponse extends Message { - public constructor( - host: ZWaveHost, - options: - | MessageDeserializationOptions - | GetLongRangeNodesResponseOptions, - ) { - super(host, options); - - if (gotDeserializationOptions(options)) { - this.moreNodes = this.payload[0] != 0; - this.segmentNumber = this.payload[1]; - const listLength = this.payload[2]; - - const listStart = 3; - const listEnd = listStart + listLength; - if (listEnd <= this.payload.length) { - const nodeBitMask = this.payload.subarray( - listStart, - listEnd, - ); - this.nodeIds = parseLongRangeNodeBitMask( - nodeBitMask, - this.listStartNode(), - ); - } else { - this.nodeIds = []; - } - } else { - this.moreNodes = options.moreNodes; - this.segmentNumber = options.segmentNumber; - this.nodeIds = options.nodeIds; - } - } - - public moreNodes: boolean; - public segmentNumber: number; - public nodeIds: readonly number[]; - - public serialize(): Buffer { - this.payload = Buffer.allocUnsafe( - 3 + NUM_LR_NODEMASK_SEGMENT_BYTES, - ); - - this.payload[0] = this.moreNodes ? 1 : 0; - this.payload[1] = this.segmentNumber; - this.payload[2] = NUM_LR_NODEMASK_SEGMENT_BYTES; - - const nodeBitMask = encodeLongRangeNodeBitMask( - this.nodeIds, - this.listStartNode(), - ); - nodeBitMask.copy(this.payload, 3); - - return super.serialize(); - } - - private listStartNode(): number { - return 256 + NUM_LR_NODES_PER_SEGMENT * this.segmentNumber; - } -}