@zwave-js/nvmedit 8.9.0-beta.4-pr-3789-c208add
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +53 -0
- package/bin/nvmedit.js +2 -0
- package/build/cli.d.ts +3 -0
- package/build/cli.d.ts.map +1 -0
- package/build/cli.js +175 -0
- package/build/cli.js.map +1 -0
- package/build/consts.d.ts +4 -0
- package/build/consts.d.ts.map +1 -0
- package/build/consts.js +7 -0
- package/build/consts.js.map +1 -0
- package/build/convert.d.ts +86 -0
- package/build/convert.d.ts.map +1 -0
- package/build/convert.js +796 -0
- package/build/convert.js.map +1 -0
- package/build/files/ApplicationCCsFile.d.ts +22 -0
- package/build/files/ApplicationCCsFile.d.ts.map +1 -0
- package/build/files/ApplicationCCsFile.js +75 -0
- package/build/files/ApplicationCCsFile.js.map +1 -0
- package/build/files/ApplicationDataFile.d.ts +12 -0
- package/build/files/ApplicationDataFile.d.ts.map +1 -0
- package/build/files/ApplicationDataFile.js +31 -0
- package/build/files/ApplicationDataFile.js.map +1 -0
- package/build/files/ApplicationRFConfigFile.d.ts +21 -0
- package/build/files/ApplicationRFConfigFile.d.ts.map +1 -0
- package/build/files/ApplicationRFConfigFile.js +71 -0
- package/build/files/ApplicationRFConfigFile.js.map +1 -0
- package/build/files/ApplicationTypeFile.d.ts +24 -0
- package/build/files/ApplicationTypeFile.d.ts.map +1 -0
- package/build/files/ApplicationTypeFile.js +52 -0
- package/build/files/ApplicationTypeFile.js.map +1 -0
- package/build/files/ControllerInfoFile.d.ts +44 -0
- package/build/files/ControllerInfoFile.d.ts.map +1 -0
- package/build/files/ControllerInfoFile.js +136 -0
- package/build/files/ControllerInfoFile.js.map +1 -0
- package/build/files/NVMFile.d.ts +48 -0
- package/build/files/NVMFile.d.ts.map +1 -0
- package/build/files/NVMFile.js +129 -0
- package/build/files/NVMFile.js.map +1 -0
- package/build/files/NodeInfoFiles.d.ts +38 -0
- package/build/files/NodeInfoFiles.d.ts.map +1 -0
- package/build/files/NodeInfoFiles.js +146 -0
- package/build/files/NodeInfoFiles.js.map +1 -0
- package/build/files/ProtocolNodeMaskFiles.d.ts +48 -0
- package/build/files/ProtocolNodeMaskFiles.d.ts.map +1 -0
- package/build/files/ProtocolNodeMaskFiles.js +120 -0
- package/build/files/ProtocolNodeMaskFiles.js.map +1 -0
- package/build/files/RouteCacheFiles.d.ts +45 -0
- package/build/files/RouteCacheFiles.d.ts.map +1 -0
- package/build/files/RouteCacheFiles.js +164 -0
- package/build/files/RouteCacheFiles.js.map +1 -0
- package/build/files/SUCUpdateEntriesFile.d.ts +25 -0
- package/build/files/SUCUpdateEntriesFile.d.ts.map +1 -0
- package/build/files/SUCUpdateEntriesFile.js +82 -0
- package/build/files/SUCUpdateEntriesFile.js.map +1 -0
- package/build/files/VersionFiles.d.ts +27 -0
- package/build/files/VersionFiles.d.ts.map +1 -0
- package/build/files/VersionFiles.js +60 -0
- package/build/files/VersionFiles.js.map +1 -0
- package/build/files/index.d.ts +13 -0
- package/build/files/index.d.ts.map +1 -0
- package/build/files/index.js +25 -0
- package/build/files/index.js.map +1 -0
- package/build/index.d.ts +8 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +22 -0
- package/build/index.js.map +1 -0
- package/build/nvm3/consts.d.ts +48 -0
- package/build/nvm3/consts.d.ts.map +1 -0
- package/build/nvm3/consts.js +59 -0
- package/build/nvm3/consts.js.map +1 -0
- package/build/nvm3/nvm.d.ts +31 -0
- package/build/nvm3/nvm.d.ts.map +1 -0
- package/build/nvm3/nvm.js +146 -0
- package/build/nvm3/nvm.js.map +1 -0
- package/build/nvm3/object.d.ts +26 -0
- package/build/nvm3/object.d.ts.map +1 -0
- package/build/nvm3/object.js +196 -0
- package/build/nvm3/object.js.map +1 -0
- package/build/nvm3/page.d.ts +26 -0
- package/build/nvm3/page.d.ts.map +1 -0
- package/build/nvm3/page.js +94 -0
- package/build/nvm3/page.js.map +1 -0
- package/build/nvm3/utils.d.ts +11 -0
- package/build/nvm3/utils.d.ts.map +1 -0
- package/build/nvm3/utils.js +103 -0
- package/build/nvm3/utils.js.map +1 -0
- package/build/nvm500/EntryParsers.d.ts +27 -0
- package/build/nvm500/EntryParsers.d.ts.map +1 -0
- package/build/nvm500/EntryParsers.js +82 -0
- package/build/nvm500/EntryParsers.js.map +1 -0
- package/build/nvm500/NVMParser.d.ts +93 -0
- package/build/nvm500/NVMParser.d.ts.map +1 -0
- package/build/nvm500/NVMParser.js +524 -0
- package/build/nvm500/NVMParser.js.map +1 -0
- package/build/nvm500/parsers/Bridge_6_6x.d.ts +3 -0
- package/build/nvm500/parsers/Bridge_6_6x.d.ts.map +1 -0
- package/build/nvm500/parsers/Bridge_6_6x.js +183 -0
- package/build/nvm500/parsers/Bridge_6_6x.js.map +1 -0
- package/build/nvm500/parsers/Bridge_6_7x.d.ts +3 -0
- package/build/nvm500/parsers/Bridge_6_7x.d.ts.map +1 -0
- package/build/nvm500/parsers/Bridge_6_7x.js +199 -0
- package/build/nvm500/parsers/Bridge_6_7x.js.map +1 -0
- package/build/nvm500/parsers/Bridge_6_8x.d.ts +3 -0
- package/build/nvm500/parsers/Bridge_6_8x.d.ts.map +1 -0
- package/build/nvm500/parsers/Bridge_6_8x.js +226 -0
- package/build/nvm500/parsers/Bridge_6_8x.js.map +1 -0
- package/build/nvm500/parsers/Static_6_6x.d.ts +3 -0
- package/build/nvm500/parsers/Static_6_6x.d.ts.map +1 -0
- package/build/nvm500/parsers/Static_6_6x.js +178 -0
- package/build/nvm500/parsers/Static_6_6x.js.map +1 -0
- package/build/nvm500/parsers/Static_6_7x.d.ts +3 -0
- package/build/nvm500/parsers/Static_6_7x.d.ts.map +1 -0
- package/build/nvm500/parsers/Static_6_7x.js +194 -0
- package/build/nvm500/parsers/Static_6_7x.js.map +1 -0
- package/build/nvm500/parsers/Static_6_8x.d.ts +3 -0
- package/build/nvm500/parsers/Static_6_8x.d.ts.map +1 -0
- package/build/nvm500/parsers/Static_6_8x.js +222 -0
- package/build/nvm500/parsers/Static_6_8x.js.map +1 -0
- package/build/nvm500/shared.d.ts +53 -0
- package/build/nvm500/shared.d.ts.map +1 -0
- package/build/nvm500/shared.js +57 -0
- package/build/nvm500/shared.js.map +1 -0
- package/build/shared.d.ts +1 -0
- package/build/shared.d.ts.map +1 -0
- package/build/shared.js +2 -0
- package/build/shared.js.map +1 -0
- package/package.json +61 -0
package/build/convert.js
ADDED
|
@@ -0,0 +1,796 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.migrateNVM = exports.json700To500 = exports.json500To700 = exports.jsonToNVM500 = exports.jsonToNVM = exports.nvm500ToJSON = exports.nvmToJSON = exports.jsonToNVMObjects_v1_to_v3 = exports.jsonToNVMObjects_v0 = exports.nvmObjectsToJSON = exports.nodeHasInfo = void 0;
|
|
7
|
+
const core_1 = require("@zwave-js/core");
|
|
8
|
+
const shared_1 = require("@zwave-js/shared");
|
|
9
|
+
const semver_1 = __importDefault(require("semver"));
|
|
10
|
+
const files_1 = require("./files");
|
|
11
|
+
const nvm_1 = require("./nvm3/nvm");
|
|
12
|
+
const utils_1 = require("./nvm3/utils");
|
|
13
|
+
const NVMParser_1 = require("./nvm500/NVMParser");
|
|
14
|
+
function nodeHasInfo(node) {
|
|
15
|
+
return !node.isVirtual || Object.keys(node).length > 1;
|
|
16
|
+
}
|
|
17
|
+
exports.nodeHasInfo = nodeHasInfo;
|
|
18
|
+
function createEmptyPhysicalNode() {
|
|
19
|
+
return {
|
|
20
|
+
isVirtual: false,
|
|
21
|
+
isListening: false,
|
|
22
|
+
isFrequentListening: false,
|
|
23
|
+
isRouting: false,
|
|
24
|
+
supportedDataRates: [],
|
|
25
|
+
protocolVersion: 0,
|
|
26
|
+
optionalFunctionality: false,
|
|
27
|
+
nodeType: core_1.NodeType["Routing End Node"],
|
|
28
|
+
supportsSecurity: false,
|
|
29
|
+
supportsBeaming: false,
|
|
30
|
+
genericDeviceClass: 0,
|
|
31
|
+
specificDeviceClass: null,
|
|
32
|
+
neighbors: [],
|
|
33
|
+
sucUpdateIndex: 0,
|
|
34
|
+
appRouteLock: false,
|
|
35
|
+
routeSlaveSUC: false,
|
|
36
|
+
sucPendingUpdate: false,
|
|
37
|
+
pendingDiscovery: false,
|
|
38
|
+
lwr: null,
|
|
39
|
+
nlwr: null,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** Converts a compressed set of NVM objects to a JSON representation */
|
|
43
|
+
function nvmObjectsToJSON(applicationObjects, protocolObjects) {
|
|
44
|
+
var _a, _b, _c, _d;
|
|
45
|
+
const nodes = new Map();
|
|
46
|
+
const getNode = (id) => {
|
|
47
|
+
if (!nodes.has(id))
|
|
48
|
+
nodes.set(id, createEmptyPhysicalNode());
|
|
49
|
+
return nodes.get(id);
|
|
50
|
+
};
|
|
51
|
+
const getObject = (id) => {
|
|
52
|
+
var _a;
|
|
53
|
+
if (typeof id === "number") {
|
|
54
|
+
return (_a = protocolObjects.get(id)) !== null && _a !== void 0 ? _a : applicationObjects.get(id);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
for (const [key, obj] of protocolObjects) {
|
|
58
|
+
if (id(key))
|
|
59
|
+
return obj;
|
|
60
|
+
}
|
|
61
|
+
for (const [key, obj] of applicationObjects) {
|
|
62
|
+
if (id(key))
|
|
63
|
+
return obj;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const getObjectOrThrow = (id) => {
|
|
68
|
+
const ret = getObject(id);
|
|
69
|
+
if (ret)
|
|
70
|
+
return ret;
|
|
71
|
+
throw new Error(`Object not found`);
|
|
72
|
+
};
|
|
73
|
+
const getFileOrThrow = (id) => {
|
|
74
|
+
const obj = getObjectOrThrow(id);
|
|
75
|
+
return files_1.NVMFile.from(obj);
|
|
76
|
+
};
|
|
77
|
+
const getFile = (id) => {
|
|
78
|
+
const obj = getObject(id);
|
|
79
|
+
if (!obj)
|
|
80
|
+
return undefined;
|
|
81
|
+
return files_1.NVMFile.from(obj);
|
|
82
|
+
};
|
|
83
|
+
// Figure out how to parse the individual files
|
|
84
|
+
const protocolVersionFile = getFileOrThrow(files_1.ProtocolVersionFileID);
|
|
85
|
+
const protocolFileFormat = protocolVersionFile.format;
|
|
86
|
+
// Figure out which nodes exist
|
|
87
|
+
const nodeIds = getFileOrThrow(files_1.ProtocolNodeListFileID).nodeIds;
|
|
88
|
+
// Read all flags for all nodes
|
|
89
|
+
const appRouteLock = new Set(getFileOrThrow(files_1.ProtocolAppRouteLockNodeMaskFileID).nodeIds);
|
|
90
|
+
const routeSlaveSUC = new Set(getFileOrThrow(files_1.ProtocolRouteSlaveSUCNodeMaskFileID).nodeIds);
|
|
91
|
+
const sucPendingUpdate = new Set(getFileOrThrow(files_1.ProtocolSUCPendingUpdateNodeMaskFileID).nodeIds);
|
|
92
|
+
const isVirtual = new Set(getFileOrThrow(files_1.ProtocolVirtualNodeMaskFileID).nodeIds);
|
|
93
|
+
const pendingDiscovery = new Set(getFileOrThrow(files_1.ProtocolPendingDiscoveryNodeMaskFileID).nodeIds);
|
|
94
|
+
const routeCacheExists = new Set(getFileOrThrow(files_1.ProtocolRouteCacheExistsNodeMaskFileID).nodeIds);
|
|
95
|
+
// And create each node entry, including virtual ones
|
|
96
|
+
for (const id of nodeIds) {
|
|
97
|
+
const node = getNode(id);
|
|
98
|
+
const rememberOnlyVirtual = () => {
|
|
99
|
+
nodes.set(id, {
|
|
100
|
+
isVirtual: true,
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
// Find node info
|
|
104
|
+
let nodeInfo;
|
|
105
|
+
try {
|
|
106
|
+
if (protocolFileFormat === 0) {
|
|
107
|
+
const fileId = (0, files_1.nodeIdToNodeInfoFileIDV0)(id);
|
|
108
|
+
const file = getFileOrThrow(fileId);
|
|
109
|
+
nodeInfo = file.nodeInfo;
|
|
110
|
+
}
|
|
111
|
+
else if (protocolFileFormat <= 3) {
|
|
112
|
+
const fileId = (0, files_1.nodeIdToNodeInfoFileIDV1)(id);
|
|
113
|
+
const file = getFileOrThrow(fileId);
|
|
114
|
+
nodeInfo = file.nodeInfos.find((i) => i.nodeId === id);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
throw new Error(`Unsupported protocol file format: ${protocolFileFormat}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
if (e.message.includes("Object not found")) {
|
|
122
|
+
rememberOnlyVirtual();
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
throw e;
|
|
126
|
+
}
|
|
127
|
+
Object.assign(node, nodeInfo);
|
|
128
|
+
// Evaluate flags
|
|
129
|
+
node.isVirtual = isVirtual.has(id);
|
|
130
|
+
node.appRouteLock = appRouteLock.has(id);
|
|
131
|
+
node.routeSlaveSUC = routeSlaveSUC.has(id);
|
|
132
|
+
node.sucPendingUpdate = sucPendingUpdate.has(id);
|
|
133
|
+
node.pendingDiscovery = pendingDiscovery.has(id);
|
|
134
|
+
if (routeCacheExists.has(id)) {
|
|
135
|
+
let routeCache;
|
|
136
|
+
if (protocolFileFormat === 0) {
|
|
137
|
+
const fileId = (0, files_1.nodeIdToRouteCacheFileIDV0)(id);
|
|
138
|
+
const file = getFileOrThrow(fileId);
|
|
139
|
+
routeCache = file.routeCache;
|
|
140
|
+
}
|
|
141
|
+
else if (protocolFileFormat <= 3) {
|
|
142
|
+
const fileId = (0, files_1.nodeIdToRouteCacheFileIDV1)(id);
|
|
143
|
+
const file = getFileOrThrow(fileId);
|
|
144
|
+
routeCache = file.routeCaches.find((i) => i.nodeId === id);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
throw new Error(`Unsupported protocol file format: ${protocolFileFormat}`);
|
|
148
|
+
}
|
|
149
|
+
node.lwr = routeCache.lwr;
|
|
150
|
+
node.nlwr = routeCache.nlwr;
|
|
151
|
+
}
|
|
152
|
+
// @ts-expect-error Some fields include a nodeId, but we don't need it
|
|
153
|
+
delete node.nodeId;
|
|
154
|
+
}
|
|
155
|
+
// Now read info about the controller
|
|
156
|
+
const controllerInfoFile = getFileOrThrow(files_1.ControllerInfoFileID);
|
|
157
|
+
const sucUpdateEntries = getFileOrThrow(files_1.SUCUpdateEntriesFileID).updateEntries;
|
|
158
|
+
const rfConfigFile = getFile(files_1.ApplicationRFConfigFileID);
|
|
159
|
+
const applicationVersionFile = getFileOrThrow(files_1.ApplicationVersionFileID);
|
|
160
|
+
const applicationCCsFile = getFileOrThrow(files_1.ApplicationCCsFileID);
|
|
161
|
+
const applicationDataFile = getFile(files_1.ApplicationDataFileID);
|
|
162
|
+
const applicationTypeFile = getFileOrThrow(files_1.ApplicationTypeFileID);
|
|
163
|
+
const preferredRepeaters = (_a = getFile(files_1.ProtocolPreferredRepeatersFileID)) === null || _a === void 0 ? void 0 : _a.nodeIds;
|
|
164
|
+
const controllerProps = [
|
|
165
|
+
"nodeId",
|
|
166
|
+
"lastNodeId",
|
|
167
|
+
"staticControllerNodeId",
|
|
168
|
+
"sucLastIndex",
|
|
169
|
+
"controllerConfiguration",
|
|
170
|
+
"sucAwarenessPushNeeded",
|
|
171
|
+
"maxNodeId",
|
|
172
|
+
"reservedId",
|
|
173
|
+
"systemState",
|
|
174
|
+
"lastNodeIdLR",
|
|
175
|
+
"maxNodeIdLR",
|
|
176
|
+
"reservedIdLR",
|
|
177
|
+
"primaryLongRangeChannelId",
|
|
178
|
+
"dcdcConfig",
|
|
179
|
+
];
|
|
180
|
+
const controller = {
|
|
181
|
+
protocolVersion: `${protocolVersionFile.major}.${protocolVersionFile.minor}.${protocolVersionFile.patch}`,
|
|
182
|
+
applicationVersion: `${applicationVersionFile.major}.${applicationVersionFile.minor}.${applicationVersionFile.patch}`,
|
|
183
|
+
homeId: `0x${controllerInfoFile.homeId.toString("hex")}`,
|
|
184
|
+
...(0, shared_1.pick)(controllerInfoFile, controllerProps),
|
|
185
|
+
...(0, shared_1.pick)(applicationTypeFile, [
|
|
186
|
+
"isListening",
|
|
187
|
+
"optionalFunctionality",
|
|
188
|
+
"genericDeviceClass",
|
|
189
|
+
"specificDeviceClass",
|
|
190
|
+
]),
|
|
191
|
+
commandClasses: (0, shared_1.pick)(applicationCCsFile, [
|
|
192
|
+
"includedInsecurely",
|
|
193
|
+
"includedSecurelyInsecureCCs",
|
|
194
|
+
"includedSecurelySecureCCs",
|
|
195
|
+
]),
|
|
196
|
+
preferredRepeaters,
|
|
197
|
+
...(rfConfigFile
|
|
198
|
+
? {
|
|
199
|
+
rfConfig: {
|
|
200
|
+
rfRegion: rfConfigFile.rfRegion,
|
|
201
|
+
txPower: rfConfigFile.txPower,
|
|
202
|
+
measured0dBm: rfConfigFile.measured0dBm,
|
|
203
|
+
enablePTI: (_b = rfConfigFile.enablePTI) !== null && _b !== void 0 ? _b : null,
|
|
204
|
+
maxTXPower: (_c = rfConfigFile.maxTXPower) !== null && _c !== void 0 ? _c : null,
|
|
205
|
+
},
|
|
206
|
+
}
|
|
207
|
+
: {}),
|
|
208
|
+
sucUpdateEntries,
|
|
209
|
+
applicationData: (_d = applicationDataFile === null || applicationDataFile === void 0 ? void 0 : applicationDataFile.data.toString("hex")) !== null && _d !== void 0 ? _d : null,
|
|
210
|
+
};
|
|
211
|
+
// Make sure all props are defined
|
|
212
|
+
const optionalControllerProps = [
|
|
213
|
+
"sucAwarenessPushNeeded",
|
|
214
|
+
"lastNodeIdLR",
|
|
215
|
+
"maxNodeIdLR",
|
|
216
|
+
"reservedIdLR",
|
|
217
|
+
"primaryLongRangeChannelId",
|
|
218
|
+
"dcdcConfig",
|
|
219
|
+
"rfConfig",
|
|
220
|
+
"preferredRepeaters",
|
|
221
|
+
"applicationData",
|
|
222
|
+
];
|
|
223
|
+
for (const prop of optionalControllerProps) {
|
|
224
|
+
if (controller[prop] === undefined)
|
|
225
|
+
controller[prop] = null;
|
|
226
|
+
}
|
|
227
|
+
const ret = {
|
|
228
|
+
format: protocolFileFormat,
|
|
229
|
+
controller,
|
|
230
|
+
nodes: (0, utils_1.mapToObject)(nodes),
|
|
231
|
+
};
|
|
232
|
+
return ret;
|
|
233
|
+
}
|
|
234
|
+
exports.nvmObjectsToJSON = nvmObjectsToJSON;
|
|
235
|
+
function nvmJSONNodeToNodeInfo(nodeId, node) {
|
|
236
|
+
return {
|
|
237
|
+
nodeId,
|
|
238
|
+
...(0, shared_1.pick)(node, [
|
|
239
|
+
"isListening",
|
|
240
|
+
"isFrequentListening",
|
|
241
|
+
"isRouting",
|
|
242
|
+
"supportedDataRates",
|
|
243
|
+
"protocolVersion",
|
|
244
|
+
"optionalFunctionality",
|
|
245
|
+
"nodeType",
|
|
246
|
+
"supportsSecurity",
|
|
247
|
+
"supportsBeaming",
|
|
248
|
+
"genericDeviceClass",
|
|
249
|
+
"specificDeviceClass",
|
|
250
|
+
"neighbors",
|
|
251
|
+
"sucUpdateIndex",
|
|
252
|
+
]),
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function nvmJSONControllerToFileOptions(ctrlr) {
|
|
256
|
+
const ret = {
|
|
257
|
+
homeId: Buffer.from(ctrlr.homeId.replace(/^0x/, ""), "hex"),
|
|
258
|
+
nodeId: ctrlr.nodeId,
|
|
259
|
+
lastNodeId: ctrlr.lastNodeId,
|
|
260
|
+
staticControllerNodeId: ctrlr.staticControllerNodeId,
|
|
261
|
+
sucLastIndex: ctrlr.sucLastIndex,
|
|
262
|
+
controllerConfiguration: ctrlr.controllerConfiguration,
|
|
263
|
+
maxNodeId: ctrlr.maxNodeId,
|
|
264
|
+
reservedId: ctrlr.reservedId,
|
|
265
|
+
systemState: ctrlr.systemState,
|
|
266
|
+
};
|
|
267
|
+
if (ctrlr.sucAwarenessPushNeeded != undefined) {
|
|
268
|
+
// @ts-expect-error We're dealing with a conditional object here
|
|
269
|
+
// TS doesn't like that.
|
|
270
|
+
ret.sucAwarenessPushNeeded = ctrlr.sucAwarenessPushNeeded;
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
Object.assign(ret, (0, core_1.stripUndefined)((0, shared_1.pick)(ctrlr, [
|
|
274
|
+
"sucAwarenessPushNeeded",
|
|
275
|
+
"lastNodeIdLR",
|
|
276
|
+
"maxNodeIdLR",
|
|
277
|
+
"reservedIdLR",
|
|
278
|
+
"primaryLongRangeChannelId",
|
|
279
|
+
"dcdcConfig",
|
|
280
|
+
])));
|
|
281
|
+
}
|
|
282
|
+
return ret;
|
|
283
|
+
}
|
|
284
|
+
function serializeCommonApplicationObjects(nvm) {
|
|
285
|
+
var _a, _b;
|
|
286
|
+
const ret = [];
|
|
287
|
+
const applTypeFile = new files_1.ApplicationTypeFile((0, shared_1.pick)(nvm.controller, [
|
|
288
|
+
"isListening",
|
|
289
|
+
"optionalFunctionality",
|
|
290
|
+
"genericDeviceClass",
|
|
291
|
+
"specificDeviceClass",
|
|
292
|
+
]));
|
|
293
|
+
ret.push(applTypeFile.serialize());
|
|
294
|
+
const applCCsFile = new files_1.ApplicationCCsFile((0, shared_1.pick)(nvm.controller.commandClasses, [
|
|
295
|
+
"includedInsecurely",
|
|
296
|
+
"includedSecurelyInsecureCCs",
|
|
297
|
+
"includedSecurelySecureCCs",
|
|
298
|
+
]));
|
|
299
|
+
ret.push(applCCsFile.serialize());
|
|
300
|
+
if (nvm.controller.rfConfig) {
|
|
301
|
+
const applRFConfigFile = new files_1.ApplicationRFConfigFile({
|
|
302
|
+
...(0, shared_1.pick)(nvm.controller.rfConfig, [
|
|
303
|
+
"rfRegion",
|
|
304
|
+
"txPower",
|
|
305
|
+
"measured0dBm",
|
|
306
|
+
]),
|
|
307
|
+
enablePTI: (_a = nvm.controller.rfConfig.enablePTI) !== null && _a !== void 0 ? _a : undefined,
|
|
308
|
+
maxTXPower: (_b = nvm.controller.rfConfig.maxTXPower) !== null && _b !== void 0 ? _b : undefined,
|
|
309
|
+
});
|
|
310
|
+
ret.push(applRFConfigFile.serialize());
|
|
311
|
+
}
|
|
312
|
+
if (nvm.controller.applicationData) {
|
|
313
|
+
// TODO: ensure this is 512 bytes long
|
|
314
|
+
const applDataFile = new files_1.ApplicationDataFile({
|
|
315
|
+
data: Buffer.from(nvm.controller.applicationData, "hex"),
|
|
316
|
+
});
|
|
317
|
+
ret.push(applDataFile.serialize());
|
|
318
|
+
}
|
|
319
|
+
return ret;
|
|
320
|
+
}
|
|
321
|
+
function serializeCommonProtocolObjects(nvm) {
|
|
322
|
+
var _a;
|
|
323
|
+
const ret = [];
|
|
324
|
+
const appRouteLock = new Set();
|
|
325
|
+
const routeSlaveSUC = new Set();
|
|
326
|
+
const sucPendingUpdate = new Set();
|
|
327
|
+
const isVirtual = new Set();
|
|
328
|
+
const pendingDiscovery = new Set();
|
|
329
|
+
for (const [id, node] of Object.entries(nvm.nodes)) {
|
|
330
|
+
const nodeId = parseInt(id);
|
|
331
|
+
if (!nodeHasInfo(node)) {
|
|
332
|
+
isVirtual.add(nodeId);
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
if (node.isVirtual)
|
|
337
|
+
isVirtual.add(nodeId);
|
|
338
|
+
if (node.appRouteLock)
|
|
339
|
+
appRouteLock.add(nodeId);
|
|
340
|
+
if (node.routeSlaveSUC)
|
|
341
|
+
routeSlaveSUC.add(nodeId);
|
|
342
|
+
if (node.sucPendingUpdate)
|
|
343
|
+
sucPendingUpdate.add(nodeId);
|
|
344
|
+
if (node.pendingDiscovery)
|
|
345
|
+
pendingDiscovery.add(nodeId);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
ret.push(new files_1.ControllerInfoFile(nvmJSONControllerToFileOptions(nvm.controller)).serialize());
|
|
349
|
+
ret.push(new files_1.ProtocolAppRouteLockNodeMaskFile({
|
|
350
|
+
nodeIds: [...appRouteLock],
|
|
351
|
+
}).serialize());
|
|
352
|
+
ret.push(new files_1.ProtocolRouteSlaveSUCNodeMaskFile({
|
|
353
|
+
nodeIds: [...routeSlaveSUC],
|
|
354
|
+
}).serialize());
|
|
355
|
+
ret.push(new files_1.ProtocolSUCPendingUpdateNodeMaskFile({
|
|
356
|
+
nodeIds: [...sucPendingUpdate],
|
|
357
|
+
}).serialize());
|
|
358
|
+
ret.push(new files_1.ProtocolVirtualNodeMaskFile({
|
|
359
|
+
nodeIds: [...isVirtual],
|
|
360
|
+
}).serialize());
|
|
361
|
+
ret.push(new files_1.ProtocolPendingDiscoveryNodeMaskFile({
|
|
362
|
+
nodeIds: [...pendingDiscovery],
|
|
363
|
+
}).serialize());
|
|
364
|
+
// TODO: format >= 2: { .key = FILE_ID_LRANGE_NODE_EXIST, .size = FILE_SIZE_LRANGE_NODE_EXIST, .name = "LRANGE_NODE_EXIST"},
|
|
365
|
+
if ((_a = nvm.controller.preferredRepeaters) === null || _a === void 0 ? void 0 : _a.length) {
|
|
366
|
+
ret.push(new files_1.ProtocolPreferredRepeatersFile({
|
|
367
|
+
nodeIds: nvm.controller.preferredRepeaters,
|
|
368
|
+
}).serialize());
|
|
369
|
+
}
|
|
370
|
+
ret.push(new files_1.SUCUpdateEntriesFile({
|
|
371
|
+
updateEntries: nvm.controller.sucUpdateEntries,
|
|
372
|
+
}).serialize());
|
|
373
|
+
return ret;
|
|
374
|
+
}
|
|
375
|
+
function jsonToNVMObjects_v0(json, major, minor, patch) {
|
|
376
|
+
var _a, _b;
|
|
377
|
+
const target = (0, shared_1.cloneDeep)(json);
|
|
378
|
+
target.format = 0;
|
|
379
|
+
const applicationObjects = new Map();
|
|
380
|
+
const protocolObjects = new Map();
|
|
381
|
+
const addApplicationObjects = (...objects) => {
|
|
382
|
+
for (const o of objects) {
|
|
383
|
+
applicationObjects.set(o.key, o);
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
const addProtocolObjects = (...objects) => {
|
|
387
|
+
for (const o of objects) {
|
|
388
|
+
protocolObjects.set(o.key, o);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
// Application files
|
|
392
|
+
const [applMajor, applMinor, applPatch] = target.controller.applicationVersion.split(".").map((i) => parseInt(i));
|
|
393
|
+
const applVersionFile = new files_1.ApplicationVersionFile({
|
|
394
|
+
format: target.format,
|
|
395
|
+
major: applMajor,
|
|
396
|
+
minor: applMinor,
|
|
397
|
+
patch: applPatch,
|
|
398
|
+
});
|
|
399
|
+
addApplicationObjects(applVersionFile.serialize());
|
|
400
|
+
addApplicationObjects(...serializeCommonApplicationObjects(target));
|
|
401
|
+
// Protocol files
|
|
402
|
+
const protocolVersionFile = new files_1.ProtocolVersionFile({
|
|
403
|
+
format: target.format,
|
|
404
|
+
major,
|
|
405
|
+
minor,
|
|
406
|
+
patch,
|
|
407
|
+
});
|
|
408
|
+
addProtocolObjects(protocolVersionFile.serialize());
|
|
409
|
+
const nodeInfoFiles = new Map();
|
|
410
|
+
const routeCacheFiles = new Map();
|
|
411
|
+
const nodeInfoExists = new Set();
|
|
412
|
+
const routeCacheExists = new Set();
|
|
413
|
+
for (const [id, node] of Object.entries(target.nodes)) {
|
|
414
|
+
const nodeId = parseInt(id);
|
|
415
|
+
if (!nodeHasInfo(node))
|
|
416
|
+
continue;
|
|
417
|
+
nodeInfoExists.add(nodeId);
|
|
418
|
+
// Create/update node info file
|
|
419
|
+
const nodeInfoFileIndex = (0, files_1.nodeIdToNodeInfoFileIDV0)(nodeId);
|
|
420
|
+
nodeInfoFiles.set(nodeInfoFileIndex, new files_1.NodeInfoFileV0({
|
|
421
|
+
nodeInfo: nvmJSONNodeToNodeInfo(nodeId, node),
|
|
422
|
+
}));
|
|
423
|
+
// Create/update route cache file (if there is a route)
|
|
424
|
+
if (node.lwr || node.nlwr) {
|
|
425
|
+
routeCacheExists.add(nodeId);
|
|
426
|
+
const routeCacheFileIndex = (0, files_1.nodeIdToRouteCacheFileIDV0)(nodeId);
|
|
427
|
+
routeCacheFiles.set(routeCacheFileIndex, new files_1.RouteCacheFileV0({
|
|
428
|
+
routeCache: {
|
|
429
|
+
nodeId,
|
|
430
|
+
lwr: (_a = node.lwr) !== null && _a !== void 0 ? _a : (0, files_1.getEmptyRoute)(),
|
|
431
|
+
nlwr: (_b = node.nlwr) !== null && _b !== void 0 ? _b : (0, files_1.getEmptyRoute)(),
|
|
432
|
+
},
|
|
433
|
+
}));
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
addProtocolObjects(...serializeCommonProtocolObjects(target));
|
|
437
|
+
addProtocolObjects(new files_1.ProtocolNodeListFile({ nodeIds: [...nodeInfoExists] }).serialize());
|
|
438
|
+
addProtocolObjects(new files_1.ProtocolRouteCacheExistsNodeMaskFile({
|
|
439
|
+
nodeIds: [...routeCacheExists],
|
|
440
|
+
}).serialize());
|
|
441
|
+
if (nodeInfoFiles.size > 0) {
|
|
442
|
+
addProtocolObjects(...[...nodeInfoFiles.values()].map((f) => f.serialize()));
|
|
443
|
+
}
|
|
444
|
+
if (routeCacheFiles.size > 0) {
|
|
445
|
+
addProtocolObjects(...[...routeCacheFiles.values()].map((f) => f.serialize()));
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
applicationObjects,
|
|
449
|
+
protocolObjects,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
exports.jsonToNVMObjects_v0 = jsonToNVMObjects_v0;
|
|
453
|
+
function jsonToNVMObjects_v1_to_v3(format, json, major, minor, patch) {
|
|
454
|
+
var _a, _b;
|
|
455
|
+
const target = (0, shared_1.cloneDeep)(json);
|
|
456
|
+
target.format = format;
|
|
457
|
+
const applicationObjects = new Map();
|
|
458
|
+
const protocolObjects = new Map();
|
|
459
|
+
const addApplicationObjects = (...objects) => {
|
|
460
|
+
for (const o of objects) {
|
|
461
|
+
applicationObjects.set(o.key, o);
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
const addProtocolObjects = (...objects) => {
|
|
465
|
+
for (const o of objects) {
|
|
466
|
+
protocolObjects.set(o.key, o);
|
|
467
|
+
}
|
|
468
|
+
};
|
|
469
|
+
// Application files
|
|
470
|
+
const [applMajor, applMinor, applPatch] = target.controller.applicationVersion.split(".").map((i) => parseInt(i));
|
|
471
|
+
const applVersionFile = new files_1.ApplicationVersionFile({
|
|
472
|
+
format: target.format,
|
|
473
|
+
major: applMajor,
|
|
474
|
+
minor: applMinor,
|
|
475
|
+
patch: applPatch,
|
|
476
|
+
});
|
|
477
|
+
addApplicationObjects(applVersionFile.serialize());
|
|
478
|
+
addApplicationObjects(...serializeCommonApplicationObjects(target));
|
|
479
|
+
// Protocol files
|
|
480
|
+
const protocolVersionFile = new files_1.ProtocolVersionFile({
|
|
481
|
+
format: target.format,
|
|
482
|
+
major,
|
|
483
|
+
minor,
|
|
484
|
+
patch,
|
|
485
|
+
});
|
|
486
|
+
addProtocolObjects(protocolVersionFile.serialize());
|
|
487
|
+
const nodeInfoFiles = new Map();
|
|
488
|
+
const routeCacheFiles = new Map();
|
|
489
|
+
const nodeInfoExists = new Set();
|
|
490
|
+
const routeCacheExists = new Set();
|
|
491
|
+
for (const [id, node] of Object.entries(target.nodes)) {
|
|
492
|
+
const nodeId = parseInt(id);
|
|
493
|
+
if (!nodeHasInfo(node))
|
|
494
|
+
continue;
|
|
495
|
+
nodeInfoExists.add(nodeId);
|
|
496
|
+
// Create/update node info file
|
|
497
|
+
const nodeInfoFileIndex = (0, files_1.nodeIdToNodeInfoFileIDV1)(nodeId);
|
|
498
|
+
if (!nodeInfoFiles.has(nodeInfoFileIndex)) {
|
|
499
|
+
nodeInfoFiles.set(nodeInfoFileIndex, new files_1.NodeInfoFileV1({
|
|
500
|
+
nodeInfos: [],
|
|
501
|
+
}));
|
|
502
|
+
}
|
|
503
|
+
const nodeInfoFile = nodeInfoFiles.get(nodeInfoFileIndex);
|
|
504
|
+
nodeInfoFile.nodeInfos.push(nvmJSONNodeToNodeInfo(nodeId, node));
|
|
505
|
+
// Create/update route cache file (if there is a route)
|
|
506
|
+
if (node.lwr || node.nlwr) {
|
|
507
|
+
routeCacheExists.add(nodeId);
|
|
508
|
+
const routeCacheFileIndex = (0, files_1.nodeIdToRouteCacheFileIDV1)(nodeId);
|
|
509
|
+
if (!routeCacheFiles.has(routeCacheFileIndex)) {
|
|
510
|
+
routeCacheFiles.set(routeCacheFileIndex, new files_1.RouteCacheFileV1({
|
|
511
|
+
routeCaches: [],
|
|
512
|
+
}));
|
|
513
|
+
}
|
|
514
|
+
const routeCacheFile = routeCacheFiles.get(routeCacheFileIndex);
|
|
515
|
+
routeCacheFile.routeCaches.push({
|
|
516
|
+
nodeId,
|
|
517
|
+
lwr: (_a = node.lwr) !== null && _a !== void 0 ? _a : (0, files_1.getEmptyRoute)(),
|
|
518
|
+
nlwr: (_b = node.nlwr) !== null && _b !== void 0 ? _b : (0, files_1.getEmptyRoute)(),
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
addProtocolObjects(...serializeCommonProtocolObjects(target));
|
|
523
|
+
addProtocolObjects(new files_1.ProtocolNodeListFile({ nodeIds: [...nodeInfoExists] }).serialize());
|
|
524
|
+
addProtocolObjects(new files_1.ProtocolRouteCacheExistsNodeMaskFile({
|
|
525
|
+
nodeIds: [...routeCacheExists],
|
|
526
|
+
}).serialize());
|
|
527
|
+
if (nodeInfoFiles.size > 0) {
|
|
528
|
+
addProtocolObjects(...[...nodeInfoFiles.values()].map((f) => f.serialize()));
|
|
529
|
+
}
|
|
530
|
+
if (routeCacheFiles.size > 0) {
|
|
531
|
+
addProtocolObjects(...[...routeCacheFiles.values()].map((f) => f.serialize()));
|
|
532
|
+
}
|
|
533
|
+
return {
|
|
534
|
+
applicationObjects,
|
|
535
|
+
protocolObjects,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
exports.jsonToNVMObjects_v1_to_v3 = jsonToNVMObjects_v1_to_v3;
|
|
539
|
+
/** Reads an NVM buffer and returns its JSON representation */
|
|
540
|
+
function nvmToJSON(buffer, debugLogs = false) {
|
|
541
|
+
const nvm = (0, nvm_1.parseNVM)(buffer, debugLogs);
|
|
542
|
+
const ret = nvmObjectsToJSON(nvm.applicationObjects, nvm.protocolObjects);
|
|
543
|
+
ret.meta = (0, nvm_1.getNVMMeta)(nvm.protocolPages[0]);
|
|
544
|
+
return ret;
|
|
545
|
+
}
|
|
546
|
+
exports.nvmToJSON = nvmToJSON;
|
|
547
|
+
/** Reads an NVM buffer of a 500-series stick and returns its JSON representation */
|
|
548
|
+
function nvm500ToJSON(buffer) {
|
|
549
|
+
const parser = (0, NVMParser_1.createParser)(buffer);
|
|
550
|
+
if (!parser)
|
|
551
|
+
throw new Error("Unsupported NVM format!");
|
|
552
|
+
return parser.toJSON();
|
|
553
|
+
}
|
|
554
|
+
exports.nvm500ToJSON = nvm500ToJSON;
|
|
555
|
+
/** Takes a JSON represented NVM and converts it to binary */
|
|
556
|
+
function jsonToNVM(json, protocolVersion) {
|
|
557
|
+
const parsedVersion = semver_1.default.parse(protocolVersion);
|
|
558
|
+
if (!parsedVersion) {
|
|
559
|
+
throw new Error(`Invalid protocol version: ${protocolVersion}`);
|
|
560
|
+
}
|
|
561
|
+
let objects;
|
|
562
|
+
if (semver_1.default.gte(parsedVersion, "7.15.3")) {
|
|
563
|
+
objects = jsonToNVMObjects_v1_to_v3(3, json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
564
|
+
}
|
|
565
|
+
else if (semver_1.default.gte(parsedVersion, "7.12.0")) {
|
|
566
|
+
objects = jsonToNVMObjects_v1_to_v3(2, json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
567
|
+
}
|
|
568
|
+
else if (semver_1.default.gte(parsedVersion, "7.11.0")) {
|
|
569
|
+
objects = jsonToNVMObjects_v1_to_v3(1, json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
570
|
+
}
|
|
571
|
+
else if (semver_1.default.gte(parsedVersion, "7.0.0")) {
|
|
572
|
+
objects = jsonToNVMObjects_v0(json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
throw new Error("jsonToNVM cannot convert to a pre-7.0 NVM version");
|
|
576
|
+
}
|
|
577
|
+
return (0, nvm_1.encodeNVM)(objects.applicationObjects, objects.protocolObjects, json.meta);
|
|
578
|
+
}
|
|
579
|
+
exports.jsonToNVM = jsonToNVM;
|
|
580
|
+
/** Takes a JSON represented 500 series NVM and converts it to binary */
|
|
581
|
+
function jsonToNVM500(json, protocolVersion) {
|
|
582
|
+
// Try to find a matching implementation
|
|
583
|
+
const impl = NVMParser_1.nmvDetails500.find((p) => p.protocolVersions.includes(protocolVersion) &&
|
|
584
|
+
p.name.toLowerCase().startsWith(json.meta.library));
|
|
585
|
+
if (!impl) {
|
|
586
|
+
throw new Error(`Did not find a matching implementation for protocol version ${protocolVersion} and library ${json.meta.library}.`);
|
|
587
|
+
}
|
|
588
|
+
const serializer = new NVMParser_1.NVMSerializer(impl);
|
|
589
|
+
serializer.parseJSON(json, protocolVersion);
|
|
590
|
+
return serializer.serialize();
|
|
591
|
+
}
|
|
592
|
+
exports.jsonToNVM500 = jsonToNVM500;
|
|
593
|
+
function json500To700(json, truncateApplicationData) {
|
|
594
|
+
var _a;
|
|
595
|
+
const source = (0, shared_1.cloneDeep)(json);
|
|
596
|
+
// On the 500 series, some properties are only defined for the nodes, so we pull it off the
|
|
597
|
+
// controller's node entry
|
|
598
|
+
let controllerNode = source.nodes[source.controller.nodeId || 1]; // Little hack because TS doesn't type check the union type properly
|
|
599
|
+
if (!nodeHasInfo(controllerNode)) {
|
|
600
|
+
// No information available, use sensible defaults
|
|
601
|
+
controllerNode = {
|
|
602
|
+
isListening: true,
|
|
603
|
+
optionalFunctionality: false,
|
|
604
|
+
// Static PC Controller
|
|
605
|
+
genericDeviceClass: 0x02,
|
|
606
|
+
specificDeviceClass: 0x01,
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
let applicationData = null;
|
|
610
|
+
if (source.controller.applicationData) {
|
|
611
|
+
let raw = Buffer.from(source.controller.applicationData, "hex");
|
|
612
|
+
// Find actual start and end of application data, ignoring zeroes
|
|
613
|
+
let start = 0;
|
|
614
|
+
while (start < raw.length && raw[start] === 0) {
|
|
615
|
+
start++;
|
|
616
|
+
}
|
|
617
|
+
let end = raw.length - 1;
|
|
618
|
+
while (end > start && raw[end] === 0) {
|
|
619
|
+
end--;
|
|
620
|
+
}
|
|
621
|
+
raw = raw.slice(start, end + 1);
|
|
622
|
+
if (raw.length > 512) {
|
|
623
|
+
if (!truncateApplicationData) {
|
|
624
|
+
throw new Error("Invalid NVM JSON: Application data would be truncated! Set truncateApplicationData to true to allow this.");
|
|
625
|
+
}
|
|
626
|
+
raw = raw.slice(0, 512);
|
|
627
|
+
}
|
|
628
|
+
applicationData = raw.toString("hex");
|
|
629
|
+
}
|
|
630
|
+
let homeId;
|
|
631
|
+
if (source.controller.controllerConfiguration &
|
|
632
|
+
core_1.ControllerCapabilityFlags.OnOtherNetwork) {
|
|
633
|
+
// The controller did not start the network itself
|
|
634
|
+
if (!source.controller.learnedHomeId) {
|
|
635
|
+
throw new Error("Invalid NVM JSON: Controller is part of another network but has no learned Home ID!");
|
|
636
|
+
}
|
|
637
|
+
else if (!source.controller.nodeId) {
|
|
638
|
+
throw new Error("Invalid NVM JSON: Controller is part of another network but node ID is zero!");
|
|
639
|
+
}
|
|
640
|
+
homeId = source.controller.learnedHomeId;
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
// The controller did start the network itself
|
|
644
|
+
homeId = source.controller.ownHomeId;
|
|
645
|
+
// it is safe to set the node ID to 1
|
|
646
|
+
source.controller.nodeId = 1;
|
|
647
|
+
}
|
|
648
|
+
const ret = {
|
|
649
|
+
// Start out with format 0 (= protocol version 7.0.0), the jsonToNVM routines will do further conversion
|
|
650
|
+
format: 0,
|
|
651
|
+
controller: {
|
|
652
|
+
// This will contain the original 6.x protocol version, but the jsonToNVM routines will update it
|
|
653
|
+
protocolVersion: source.controller.protocolVersion,
|
|
654
|
+
applicationVersion: source.controller.applicationVersion,
|
|
655
|
+
homeId,
|
|
656
|
+
nodeId: source.controller.nodeId,
|
|
657
|
+
lastNodeId: source.controller.lastNodeId,
|
|
658
|
+
staticControllerNodeId: source.controller.staticControllerNodeId,
|
|
659
|
+
sucLastIndex: source.controller.sucLastIndex,
|
|
660
|
+
controllerConfiguration: source.controller.controllerConfiguration,
|
|
661
|
+
sucUpdateEntries: source.controller.sucUpdateEntries,
|
|
662
|
+
maxNodeId: source.controller.maxNodeId,
|
|
663
|
+
reservedId: source.controller.reservedId,
|
|
664
|
+
systemState: source.controller.systemState,
|
|
665
|
+
preferredRepeaters: source.controller.preferredRepeaters,
|
|
666
|
+
// RF config exists on both series but isn't compatible
|
|
667
|
+
isListening: controllerNode.isListening,
|
|
668
|
+
optionalFunctionality: controllerNode.optionalFunctionality,
|
|
669
|
+
genericDeviceClass: controllerNode.genericDeviceClass,
|
|
670
|
+
specificDeviceClass: (_a = controllerNode.specificDeviceClass) !== null && _a !== void 0 ? _a : 0,
|
|
671
|
+
commandClasses: {
|
|
672
|
+
includedInsecurely: source.controller.commandClasses,
|
|
673
|
+
includedSecurelyInsecureCCs: [],
|
|
674
|
+
includedSecurelySecureCCs: [],
|
|
675
|
+
},
|
|
676
|
+
applicationData,
|
|
677
|
+
},
|
|
678
|
+
// The node entries are actually compatible between the two JSON versions
|
|
679
|
+
// but the types are structured differently
|
|
680
|
+
nodes: source.nodes,
|
|
681
|
+
};
|
|
682
|
+
return ret;
|
|
683
|
+
}
|
|
684
|
+
exports.json500To700 = json500To700;
|
|
685
|
+
function json700To500(json) {
|
|
686
|
+
var _a;
|
|
687
|
+
const source = (0, shared_1.cloneDeep)(json);
|
|
688
|
+
const ret = {
|
|
689
|
+
format: 500,
|
|
690
|
+
controller: {
|
|
691
|
+
// This will contain the original 7.x protocol version, but the jsonToNVM routines will update it
|
|
692
|
+
protocolVersion: source.controller.protocolVersion,
|
|
693
|
+
applicationVersion: source.controller.applicationVersion,
|
|
694
|
+
// The 700 series does not distinguish between own and learned home ID in NVM
|
|
695
|
+
// We infer it from the controller configuration if we need it
|
|
696
|
+
ownHomeId: source.controller.homeId,
|
|
697
|
+
learnedHomeId: source.controller.controllerConfiguration &
|
|
698
|
+
core_1.ControllerCapabilityFlags.OnOtherNetwork
|
|
699
|
+
? source.controller.homeId
|
|
700
|
+
: null,
|
|
701
|
+
nodeId: source.controller.nodeId,
|
|
702
|
+
lastNodeId: source.controller.lastNodeId,
|
|
703
|
+
staticControllerNodeId: source.controller.staticControllerNodeId,
|
|
704
|
+
sucLastIndex: source.controller.sucLastIndex,
|
|
705
|
+
controllerConfiguration: source.controller.controllerConfiguration,
|
|
706
|
+
sucUpdateEntries: source.controller.sucUpdateEntries,
|
|
707
|
+
maxNodeId: source.controller.maxNodeId,
|
|
708
|
+
reservedId: source.controller.reservedId,
|
|
709
|
+
systemState: source.controller.systemState,
|
|
710
|
+
watchdogStarted: 0,
|
|
711
|
+
preferredRepeaters: (_a = json.controller.preferredRepeaters) !== null && _a !== void 0 ? _a : [],
|
|
712
|
+
// RF config exists on both series but isn't compatible. So set the default
|
|
713
|
+
rfConfig: {
|
|
714
|
+
powerLevelNormal: [255, 255, 255],
|
|
715
|
+
powerLevelLow: [255, 255, 255],
|
|
716
|
+
powerMode: 255,
|
|
717
|
+
powerModeExtintEnable: 255,
|
|
718
|
+
powerModeWutTimeout: 0xffffffff,
|
|
719
|
+
},
|
|
720
|
+
commandClasses: source.controller.commandClasses.includedInsecurely,
|
|
721
|
+
applicationData: source.controller.applicationData,
|
|
722
|
+
},
|
|
723
|
+
// The node entries are actually compatible between the two JSON versions
|
|
724
|
+
// just the types are structured differently
|
|
725
|
+
nodes: source.nodes,
|
|
726
|
+
};
|
|
727
|
+
return ret;
|
|
728
|
+
}
|
|
729
|
+
exports.json700To500 = json700To500;
|
|
730
|
+
/** Converts the given source NVM into a format that is compatible with the given target NVM */
|
|
731
|
+
function migrateNVM(source, target) {
|
|
732
|
+
let sourceJSON;
|
|
733
|
+
let targetJSON;
|
|
734
|
+
let sourceIs500;
|
|
735
|
+
let targetIs500;
|
|
736
|
+
try {
|
|
737
|
+
sourceJSON = nvmToJSON(source);
|
|
738
|
+
sourceIs500 = false;
|
|
739
|
+
}
|
|
740
|
+
catch (e) {
|
|
741
|
+
try {
|
|
742
|
+
sourceJSON = nvm500ToJSON(source);
|
|
743
|
+
sourceIs500 = true;
|
|
744
|
+
}
|
|
745
|
+
catch (ee) {
|
|
746
|
+
throw new Error("Could not parse source NVM - invalid format!");
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
try {
|
|
750
|
+
targetJSON = nvmToJSON(target);
|
|
751
|
+
targetIs500 = false;
|
|
752
|
+
}
|
|
753
|
+
catch (e) {
|
|
754
|
+
try {
|
|
755
|
+
targetJSON = nvm500ToJSON(target);
|
|
756
|
+
targetIs500 = true;
|
|
757
|
+
}
|
|
758
|
+
catch (ee) {
|
|
759
|
+
throw new Error("Could not parse target NVM - invalid format!");
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
if (sourceIs500 && targetIs500) {
|
|
763
|
+
// Both are 500, so we just need to update the metadata to match the target
|
|
764
|
+
const json = {
|
|
765
|
+
...sourceJSON,
|
|
766
|
+
meta: targetJSON.meta,
|
|
767
|
+
};
|
|
768
|
+
return jsonToNVM500(json, targetJSON.controller.protocolVersion);
|
|
769
|
+
}
|
|
770
|
+
else if (sourceIs500 && !targetIs500) {
|
|
771
|
+
// We need to upgrade the source to 700 series
|
|
772
|
+
const json = {
|
|
773
|
+
...json500To700(sourceJSON, true),
|
|
774
|
+
meta: targetJSON.meta,
|
|
775
|
+
};
|
|
776
|
+
return jsonToNVM(json, targetJSON.controller.protocolVersion);
|
|
777
|
+
}
|
|
778
|
+
else if (!sourceIs500 && targetIs500) {
|
|
779
|
+
// We need to downgrade the source to 500 series
|
|
780
|
+
const json = {
|
|
781
|
+
...json700To500(sourceJSON),
|
|
782
|
+
meta: targetJSON.meta,
|
|
783
|
+
};
|
|
784
|
+
return jsonToNVM500(json, targetJSON.controller.protocolVersion);
|
|
785
|
+
}
|
|
786
|
+
else {
|
|
787
|
+
// Both are 700, so we just need to update the metadata to match the target
|
|
788
|
+
const json = {
|
|
789
|
+
...sourceJSON,
|
|
790
|
+
meta: targetJSON.meta,
|
|
791
|
+
};
|
|
792
|
+
return jsonToNVM(json, targetJSON.controller.protocolVersion);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
exports.migrateNVM = migrateNVM;
|
|
796
|
+
//# sourceMappingURL=convert.js.map
|