Skip to content

Commit

Permalink
fix: include LR node information in NVM conversion (#6846)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlCalzone authored May 14, 2024
1 parent ce7e360 commit 3efb13e
Show file tree
Hide file tree
Showing 7 changed files with 332 additions and 18 deletions.
10 changes: 6 additions & 4 deletions packages/core/src/capabilities/NodeInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,13 +266,15 @@ export function parseNodeProtocolInfo(

let nodeType: NodeType;
switch (capability & 0b1010) {
case 0b1000:
nodeType = NodeType["End Node"];
break;
case 0b0010:
default:
nodeType = NodeType.Controller;
break;
case 0b1000:
// Routing end node
default:
// Non-routing end node
nodeType = NodeType["End Node"];
break;
}

const hasSpecificDeviceClass = !!(capability & 0b100);
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/consts/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/** Max number of nodes in a ZWave network */
export const MAX_NODES = 232;

/** Max number of nodes in a Z-Wave LR network */
export const MAX_NODES_LR = 4000; // FIXME: This seems too even, figure out the exact number

/** The broadcast target node id */
export const NODE_ID_BROADCAST = 0xff;

Expand Down
16 changes: 8 additions & 8 deletions packages/nvmedit/src/convert.test.ts.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ Generated by [AVA](https://avajs.dev).
6,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand All @@ -247,7 +247,7 @@ Generated by [AVA](https://avajs.dev).
6,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand All @@ -274,7 +274,7 @@ Generated by [AVA](https://avajs.dev).
6,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand All @@ -301,7 +301,7 @@ Generated by [AVA](https://avajs.dev).
6,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand Down Expand Up @@ -900,7 +900,7 @@ Generated by [AVA](https://avajs.dev).
12,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand Down Expand Up @@ -932,7 +932,7 @@ Generated by [AVA](https://avajs.dev).
12,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand Down Expand Up @@ -964,7 +964,7 @@ Generated by [AVA](https://avajs.dev).
12,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand Down Expand Up @@ -992,7 +992,7 @@ Generated by [AVA](https://avajs.dev).
8,
],
nlwr: null,
nodeType: 0,
nodeType: 1,
optionalFunctionality: true,
pendingDiscovery: false,
protocolVersion: 3,
Expand Down
Binary file modified packages/nvmedit/src/convert.test.ts.snap
Binary file not shown.
123 changes: 123 additions & 0 deletions packages/nvmedit/src/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ import {
ControllerInfoFile,
ControllerInfoFileID,
type ControllerInfoFileOptions,
type LRNodeInfo,
LRNodeInfoFileV5,
NVMFile,
type NodeInfo,
NodeInfoFileV0,
NodeInfoFileV1,
ProtocolAppRouteLockNodeMaskFile,
ProtocolAppRouteLockNodeMaskFileID,
ProtocolLRNodeListFile,
ProtocolLRNodeListFileID,
ProtocolNodeListFile,
ProtocolNodeListFileID,
ProtocolPendingDiscoveryNodeMaskFile,
Expand All @@ -62,6 +66,7 @@ import {
type SUCUpdateEntry,
SUC_UPDATES_PER_FILE_V5,
getEmptyRoute,
nodeIdToLRNodeInfoFileIDV5,
nodeIdToNodeInfoFileIDV0,
nodeIdToNodeInfoFileIDV1,
nodeIdToRouteCacheFileIDV0,
Expand Down Expand Up @@ -94,6 +99,7 @@ export interface NVMJSON {
meta?: NVMMeta;
controller: NVMJSONController;
nodes: Record<number, NVMJSONNode>;
lrNodes?: Record<number, NVMJSONLRNode>;
}

export interface NVMJSONController {
Expand Down Expand Up @@ -166,6 +172,13 @@ export interface NVMJSONVirtualNode {
isVirtual: true;
}

export interface NVMJSONLRNode
extends Omit<NodeProtocolInfo, "hasSpecificDeviceClass">
{
genericDeviceClass: number;
specificDeviceClass?: number | null;
}

export type NVMJSONNode = NVMJSONNodeWithInfo | NVMJSONVirtualNode;

type ParsedNVM =
Expand Down Expand Up @@ -210,6 +223,22 @@ function createEmptyPhysicalNode(): NVMJSONNodeWithInfo {
};
}

function createEmptyLRNode(): NVMJSONLRNode {
return {
isListening: false,
isFrequentListening: false,
isRouting: false,
supportedDataRates: [],
protocolVersion: 3,
optionalFunctionality: false,
nodeType: NodeType["End Node"],
supportsSecurity: true,
supportsBeaming: false,
genericDeviceClass: 0,
specificDeviceClass: null,
};
}

/** Converts a compressed set of NVM objects to a JSON representation */
export function nvmObjectsToJSON(
objects: ReadonlyMap<number, NVM3Object>,
Expand All @@ -220,6 +249,12 @@ export function nvmObjectsToJSON(
return nodes.get(id)!;
};

const lrNodes = new Map<number, NVMJSONLRNode>();
const getLRNode = (id: number): NVMJSONLRNode => {
if (!lrNodes.has(id)) lrNodes.set(id, createEmptyLRNode());
return lrNodes.get(id)!;
};

const getObject = (
id: number | ((id: number) => boolean),
): NVM3Object | undefined => {
Expand Down Expand Up @@ -391,6 +426,29 @@ export function nvmObjectsToJSON(
delete node.nodeId;
}

// If they exist, read info about LR nodes
const lrNodeIds = getFile<ProtocolLRNodeListFile>(
ProtocolLRNodeListFileID,
protocolVersion,
)?.nodeIds;
if (lrNodeIds) {
for (const id of lrNodeIds) {
const node = getLRNode(id);

// Find node info
const fileId = nodeIdToLRNodeInfoFileIDV5(id);
const file = getFileOrThrow<LRNodeInfoFileV5>(
fileId,
protocolVersion,
);
const { nodeId, ...nodeInfo } = file.nodeInfos.find((i) =>
i.nodeId === id
)!;

Object.assign(node, nodeInfo);
}
}

// Now read info about the controller
const controllerInfoFile = getFileOrThrow<ControllerInfoFile>(
ControllerInfoFileID,
Expand Down Expand Up @@ -538,6 +596,9 @@ export function nvmObjectsToJSON(
controller,
nodes: mapToObject(nodes),
};
if (lrNodes.size > 0) {
ret.lrNodes = mapToObject(lrNodes);
}

return ret;
}
Expand Down Expand Up @@ -566,6 +627,28 @@ function nvmJSONNodeToNodeInfo(
};
}

function nvmJSONLRNodeToLRNodeInfo(
nodeId: number,
node: NVMJSONLRNode,
): LRNodeInfo {
return {
nodeId,
...pick(node, [
"isListening",
"isFrequentListening",
"isRouting",
"supportedDataRates",
"protocolVersion",
"optionalFunctionality",
"nodeType",
"supportsSecurity",
"supportsBeaming",
"genericDeviceClass",
"specificDeviceClass",
]),
};
}

function nvmJSONControllerToFileOptions(
ctrlr: NVMJSONController,
): ControllerInfoFileOptions {
Expand Down Expand Up @@ -989,8 +1072,10 @@ export function jsonToNVMObjects_v7_11_0(
addProtocolObjects(protocolVersionFile.serialize());

const nodeInfoFiles = new Map<number, NodeInfoFileV1>();
const lrNodeInfoFiles = new Map<number, LRNodeInfoFileV5>();
const routeCacheFiles = new Map<number, RouteCacheFileV1>();
const nodeInfoExists = new Set<number>();
const lrNodeInfoExists = new Set<number>();
const routeCacheExists = new Set<number>();

for (const [id, node] of Object.entries(target.nodes)) {
Expand Down Expand Up @@ -1036,6 +1121,31 @@ export function jsonToNVMObjects_v7_11_0(
}
}

if (target.lrNodes) {
for (const [id, node] of Object.entries(target.lrNodes)) {
const nodeId = parseInt(id);

lrNodeInfoExists.add(nodeId);

// Create/update node info file
const nodeInfoFileIndex = nodeIdToLRNodeInfoFileIDV5(nodeId);
if (!lrNodeInfoFiles.has(nodeInfoFileIndex)) {
lrNodeInfoFiles.set(
nodeInfoFileIndex,
new LRNodeInfoFileV5({
nodeInfos: [],
fileVersion: target.controller.protocolVersion,
}),
);
}
const nodeInfoFile = lrNodeInfoFiles.get(nodeInfoFileIndex)!;

nodeInfoFile.nodeInfos.push(
nvmJSONLRNodeToLRNodeInfo(nodeId, node),
);
}
}

// For v3+ targets, the ControllerInfoFile must contain the LongRange properties
// or the controller will ignore the file and not have a home ID
if (targetProtocolFormat >= 3) {
Expand Down Expand Up @@ -1072,6 +1182,18 @@ export function jsonToNVMObjects_v7_11_0(
);
}

if (lrNodeInfoFiles.size > 0) {
addProtocolObjects(
new ProtocolLRNodeListFile({
nodeIds: [...lrNodeInfoExists],
fileVersion: target.controller.protocolVersion,
}).serialize(),
);
addProtocolObjects(
...[...lrNodeInfoFiles.values()].map((f) => f.serialize()),
);
}

return {
applicationObjects,
protocolObjects,
Expand Down Expand Up @@ -1526,6 +1648,7 @@ export function migrateNVM(sourceNVM: Buffer, targetNVM: Buffer): Buffer {
} else if (source.type === 500 && target.type === 700) {
// We need to upgrade the source to 700 series
const json: Required<NVMJSON> = {
lrNodes: {},
...json500To700(source.json, true),
meta: target.json.meta,
};
Expand Down
Loading

0 comments on commit 3efb13e

Please sign in to comment.