@zwave-js/nvmedit 10.6.0 → 10.10.0
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/build/consts.d.ts +1 -0
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +3 -1
- package/build/consts.js.map +1 -1
- package/build/convert.d.ts +4 -3
- package/build/convert.d.ts.map +1 -1
- package/build/convert.js +237 -94
- package/build/convert.js.map +1 -1
- package/build/files/ApplicationRFConfigFile.d.ts +4 -2
- package/build/files/ApplicationRFConfigFile.d.ts.map +1 -1
- package/build/files/ApplicationRFConfigFile.js +38 -18
- package/build/files/ApplicationRFConfigFile.js.map +1 -1
- package/build/files/NVMFile.d.ts +3 -1
- package/build/files/NVMFile.d.ts.map +1 -1
- package/build/files/NVMFile.js +3 -1
- package/build/files/NVMFile.js.map +1 -1
- package/build/files/SUCUpdateEntriesFile.d.ts +13 -2
- package/build/files/SUCUpdateEntriesFile.d.ts.map +1 -1
- package/build/files/SUCUpdateEntriesFile.js +58 -12
- package/build/files/SUCUpdateEntriesFile.js.map +1 -1
- package/build/nvm3/nvm.js.map +1 -1
- package/build/nvm3/utils.js +1 -1
- package/build/nvm3/utils.js.map +1 -1
- package/package.json +3 -3
package/build/convert.js
CHANGED
|
@@ -3,10 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.migrateNVM = exports.json700To500 = exports.json500To700 = exports.jsonToNVM500 = exports.jsonToNVM = exports.nvm500ToJSON = exports.nvmToJSON = exports.
|
|
6
|
+
exports.migrateNVM = exports.json700To500 = exports.json500To700 = exports.jsonToNVM500 = exports.jsonToNVM = exports.nvm500ToJSON = exports.nvmToJSON = exports.jsonToNVMObjects_v7_11_0 = exports.jsonToNVMObjects_v7_0_0 = exports.nvmObjectsToJSON = exports.nodeHasInfo = void 0;
|
|
7
7
|
const safe_1 = require("@zwave-js/core/safe");
|
|
8
8
|
const safe_2 = require("@zwave-js/shared/safe");
|
|
9
|
+
const typeguards_1 = require("alcalzone-shared/typeguards");
|
|
9
10
|
const semver_1 = __importDefault(require("semver"));
|
|
11
|
+
const consts_1 = require("./consts");
|
|
10
12
|
const files_1 = require("./files");
|
|
11
13
|
const nvm_1 = require("./nvm3/nvm");
|
|
12
14
|
const utils_1 = require("./nvm3/utils");
|
|
@@ -68,28 +70,34 @@ function nvmObjectsToJSON(applicationObjects, protocolObjects) {
|
|
|
68
70
|
return ret;
|
|
69
71
|
throw new safe_1.ZWaveError(`Object${typeof id === "number" ? ` ${id}` : ""} not found!`, safe_1.ZWaveErrorCodes.NVM_ObjectNotFound);
|
|
70
72
|
};
|
|
71
|
-
const getFileOrThrow = (id) => {
|
|
73
|
+
const getFileOrThrow = (id, fileVersion) => {
|
|
72
74
|
const obj = getObjectOrThrow(id);
|
|
73
|
-
return files_1.NVMFile.from(obj);
|
|
75
|
+
return files_1.NVMFile.from(obj, fileVersion);
|
|
74
76
|
};
|
|
75
|
-
const getFile = (id) => {
|
|
77
|
+
const getFile = (id, fileVersion) => {
|
|
76
78
|
const obj = getObject(id);
|
|
77
79
|
if (!obj)
|
|
78
80
|
return undefined;
|
|
79
|
-
return files_1.NVMFile.from(obj);
|
|
81
|
+
return files_1.NVMFile.from(obj, fileVersion);
|
|
80
82
|
};
|
|
83
|
+
// === Protocol NVM files ===
|
|
81
84
|
// Figure out how to parse the individual files
|
|
82
|
-
const protocolVersionFile = getFileOrThrow(files_1.ProtocolVersionFileID);
|
|
85
|
+
const protocolVersionFile = getFileOrThrow(files_1.ProtocolVersionFileID, "7.0.0");
|
|
83
86
|
const protocolFileFormat = protocolVersionFile.format;
|
|
87
|
+
const protocolVersion = `${protocolVersionFile.major}.${protocolVersionFile.minor}.${protocolVersionFile.patch}`;
|
|
88
|
+
// Bail early if the NVM uses a protocol file format that's newer than we support
|
|
89
|
+
if (protocolFileFormat > consts_1.MAX_PROTOCOL_FILE_FORMAT) {
|
|
90
|
+
throw new safe_1.ZWaveError(`Unsupported protocol file format: ${protocolFileFormat}`, safe_1.ZWaveErrorCodes.NVM_NotSupported, { protocolFileFormat });
|
|
91
|
+
}
|
|
84
92
|
// Figure out which nodes exist
|
|
85
|
-
const nodeIds = getFileOrThrow(files_1.ProtocolNodeListFileID).nodeIds;
|
|
93
|
+
const nodeIds = getFileOrThrow(files_1.ProtocolNodeListFileID, protocolVersion).nodeIds;
|
|
86
94
|
// Read all flags for all nodes
|
|
87
|
-
const appRouteLock = new Set(getFileOrThrow(files_1.ProtocolAppRouteLockNodeMaskFileID).nodeIds);
|
|
88
|
-
const routeSlaveSUC = new Set(getFileOrThrow(files_1.ProtocolRouteSlaveSUCNodeMaskFileID).nodeIds);
|
|
89
|
-
const sucPendingUpdate = new Set(getFileOrThrow(files_1.ProtocolSUCPendingUpdateNodeMaskFileID).nodeIds);
|
|
90
|
-
const isVirtual = new Set(getFileOrThrow(files_1.ProtocolVirtualNodeMaskFileID).nodeIds);
|
|
91
|
-
const pendingDiscovery = new Set(getFileOrThrow(files_1.ProtocolPendingDiscoveryNodeMaskFileID).nodeIds);
|
|
92
|
-
const routeCacheExists = new Set(getFileOrThrow(files_1.ProtocolRouteCacheExistsNodeMaskFileID).nodeIds);
|
|
95
|
+
const appRouteLock = new Set(getFileOrThrow(files_1.ProtocolAppRouteLockNodeMaskFileID, protocolVersion).nodeIds);
|
|
96
|
+
const routeSlaveSUC = new Set(getFileOrThrow(files_1.ProtocolRouteSlaveSUCNodeMaskFileID, protocolVersion).nodeIds);
|
|
97
|
+
const sucPendingUpdate = new Set(getFileOrThrow(files_1.ProtocolSUCPendingUpdateNodeMaskFileID, protocolVersion).nodeIds);
|
|
98
|
+
const isVirtual = new Set(getFileOrThrow(files_1.ProtocolVirtualNodeMaskFileID, protocolVersion).nodeIds);
|
|
99
|
+
const pendingDiscovery = new Set(getFileOrThrow(files_1.ProtocolPendingDiscoveryNodeMaskFileID, protocolVersion).nodeIds);
|
|
100
|
+
const routeCacheExists = new Set(getFileOrThrow(files_1.ProtocolRouteCacheExistsNodeMaskFileID, protocolVersion).nodeIds);
|
|
93
101
|
// And create each node entry, including virtual ones
|
|
94
102
|
for (const id of nodeIds) {
|
|
95
103
|
const node = getNode(id);
|
|
@@ -103,17 +111,14 @@ function nvmObjectsToJSON(applicationObjects, protocolObjects) {
|
|
|
103
111
|
try {
|
|
104
112
|
if (protocolFileFormat === 0) {
|
|
105
113
|
const fileId = (0, files_1.nodeIdToNodeInfoFileIDV0)(id);
|
|
106
|
-
const file = getFileOrThrow(fileId);
|
|
114
|
+
const file = getFileOrThrow(fileId, protocolVersion);
|
|
107
115
|
nodeInfo = file.nodeInfo;
|
|
108
116
|
}
|
|
109
|
-
else
|
|
117
|
+
else {
|
|
110
118
|
const fileId = (0, files_1.nodeIdToNodeInfoFileIDV1)(id);
|
|
111
|
-
const file = getFileOrThrow(fileId);
|
|
119
|
+
const file = getFileOrThrow(fileId, protocolVersion);
|
|
112
120
|
nodeInfo = file.nodeInfos.find((i) => i.nodeId === id);
|
|
113
121
|
}
|
|
114
|
-
else {
|
|
115
|
-
throw new safe_1.ZWaveError(`Unsupported protocol file format: ${protocolFileFormat}`, safe_1.ZWaveErrorCodes.NVM_NotSupported);
|
|
116
|
-
}
|
|
117
122
|
}
|
|
118
123
|
catch (e) {
|
|
119
124
|
if (e.message.includes("Object not found")) {
|
|
@@ -133,17 +138,14 @@ function nvmObjectsToJSON(applicationObjects, protocolObjects) {
|
|
|
133
138
|
let routeCache;
|
|
134
139
|
if (protocolFileFormat === 0) {
|
|
135
140
|
const fileId = (0, files_1.nodeIdToRouteCacheFileIDV0)(id);
|
|
136
|
-
const file = getFile(fileId);
|
|
141
|
+
const file = getFile(fileId, protocolVersion);
|
|
137
142
|
routeCache = file?.routeCache;
|
|
138
143
|
}
|
|
139
|
-
else
|
|
144
|
+
else {
|
|
140
145
|
const fileId = (0, files_1.nodeIdToRouteCacheFileIDV1)(id);
|
|
141
|
-
const file = getFile(fileId);
|
|
146
|
+
const file = getFile(fileId, protocolVersion);
|
|
142
147
|
routeCache = file?.routeCaches.find((i) => i.nodeId === id);
|
|
143
148
|
}
|
|
144
|
-
else {
|
|
145
|
-
throw new safe_1.ZWaveError(`Unsupported protocol file format: ${protocolFileFormat}`, safe_1.ZWaveErrorCodes.NVM_NotSupported);
|
|
146
|
-
}
|
|
147
149
|
if (routeCache) {
|
|
148
150
|
node.lwr = routeCache.lwr;
|
|
149
151
|
node.nlwr = routeCache.nlwr;
|
|
@@ -153,14 +155,29 @@ function nvmObjectsToJSON(applicationObjects, protocolObjects) {
|
|
|
153
155
|
delete node.nodeId;
|
|
154
156
|
}
|
|
155
157
|
// Now read info about the controller
|
|
156
|
-
const controllerInfoFile = getFileOrThrow(files_1.ControllerInfoFileID);
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
158
|
+
const controllerInfoFile = getFileOrThrow(files_1.ControllerInfoFileID, protocolVersion);
|
|
159
|
+
let sucUpdateEntries;
|
|
160
|
+
if (protocolFileFormat < 5) {
|
|
161
|
+
sucUpdateEntries = getFileOrThrow(files_1.SUCUpdateEntriesFileIDV0, protocolVersion).updateEntries;
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
// V5 has split the entries into multiple files
|
|
165
|
+
sucUpdateEntries = [];
|
|
166
|
+
for (let index = 0; index < consts_1.SUC_MAX_UPDATES; index += files_1.SUC_UPDATES_PER_FILE_V5) {
|
|
167
|
+
const file = getFile((0, files_1.sucUpdateIndexToSUCUpdateEntriesFileIDV5)(index), protocolVersion);
|
|
168
|
+
if (!file)
|
|
169
|
+
break;
|
|
170
|
+
sucUpdateEntries.push(...file.updateEntries);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// === Application NVM files ===
|
|
174
|
+
const applicationVersionFile = getFileOrThrow(files_1.ApplicationVersionFileID, "7.0.0");
|
|
175
|
+
const applicationVersion = `${applicationVersionFile.major}.${applicationVersionFile.minor}.${applicationVersionFile.patch}`;
|
|
176
|
+
const rfConfigFile = getFile(files_1.ApplicationRFConfigFileID, applicationVersion);
|
|
177
|
+
const applicationCCsFile = getFileOrThrow(files_1.ApplicationCCsFileID, applicationVersion);
|
|
178
|
+
const applicationDataFile = getFile(files_1.ApplicationDataFileID, applicationVersion);
|
|
179
|
+
const applicationTypeFile = getFileOrThrow(files_1.ApplicationTypeFileID, applicationVersion);
|
|
180
|
+
const preferredRepeaters = getFile(files_1.ProtocolPreferredRepeatersFileID, applicationVersion)?.nodeIds;
|
|
164
181
|
const controllerProps = [
|
|
165
182
|
"nodeId",
|
|
166
183
|
"lastNodeId",
|
|
@@ -283,18 +300,24 @@ function nvmJSONControllerToFileOptions(ctrlr) {
|
|
|
283
300
|
}
|
|
284
301
|
function serializeCommonApplicationObjects(nvm) {
|
|
285
302
|
const ret = [];
|
|
286
|
-
const applTypeFile = new files_1.ApplicationTypeFile(
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
303
|
+
const applTypeFile = new files_1.ApplicationTypeFile({
|
|
304
|
+
...(0, safe_2.pick)(nvm.controller, [
|
|
305
|
+
"isListening",
|
|
306
|
+
"optionalFunctionality",
|
|
307
|
+
"genericDeviceClass",
|
|
308
|
+
"specificDeviceClass",
|
|
309
|
+
]),
|
|
310
|
+
fileVersion: nvm.controller.applicationVersion,
|
|
311
|
+
});
|
|
292
312
|
ret.push(applTypeFile.serialize());
|
|
293
|
-
const applCCsFile = new files_1.ApplicationCCsFile(
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
313
|
+
const applCCsFile = new files_1.ApplicationCCsFile({
|
|
314
|
+
...(0, safe_2.pick)(nvm.controller.commandClasses, [
|
|
315
|
+
"includedInsecurely",
|
|
316
|
+
"includedSecurelyInsecureCCs",
|
|
317
|
+
"includedSecurelySecureCCs",
|
|
318
|
+
]),
|
|
319
|
+
fileVersion: nvm.controller.applicationVersion,
|
|
320
|
+
});
|
|
298
321
|
ret.push(applCCsFile.serialize());
|
|
299
322
|
if (nvm.controller.rfConfig) {
|
|
300
323
|
const applRFConfigFile = new files_1.ApplicationRFConfigFile({
|
|
@@ -305,6 +328,7 @@ function serializeCommonApplicationObjects(nvm) {
|
|
|
305
328
|
]),
|
|
306
329
|
enablePTI: nvm.controller.rfConfig.enablePTI ?? undefined,
|
|
307
330
|
maxTXPower: nvm.controller.rfConfig.maxTXPower ?? undefined,
|
|
331
|
+
fileVersion: nvm.controller.applicationVersion,
|
|
308
332
|
});
|
|
309
333
|
ret.push(applRFConfigFile.serialize());
|
|
310
334
|
}
|
|
@@ -312,6 +336,7 @@ function serializeCommonApplicationObjects(nvm) {
|
|
|
312
336
|
// TODO: ensure this is 512 bytes long
|
|
313
337
|
const applDataFile = new files_1.ApplicationDataFile({
|
|
314
338
|
data: Buffer.from(nvm.controller.applicationData, "hex"),
|
|
339
|
+
fileVersion: nvm.controller.applicationVersion,
|
|
315
340
|
});
|
|
316
341
|
ret.push(applDataFile.serialize());
|
|
317
342
|
}
|
|
@@ -346,33 +371,58 @@ function serializeCommonProtocolObjects(nvm) {
|
|
|
346
371
|
ret.push(new files_1.ControllerInfoFile(nvmJSONControllerToFileOptions(nvm.controller)).serialize());
|
|
347
372
|
ret.push(new files_1.ProtocolAppRouteLockNodeMaskFile({
|
|
348
373
|
nodeIds: [...appRouteLock],
|
|
374
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
349
375
|
}).serialize());
|
|
350
376
|
ret.push(new files_1.ProtocolRouteSlaveSUCNodeMaskFile({
|
|
351
377
|
nodeIds: [...routeSlaveSUC],
|
|
378
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
352
379
|
}).serialize());
|
|
353
380
|
ret.push(new files_1.ProtocolSUCPendingUpdateNodeMaskFile({
|
|
354
381
|
nodeIds: [...sucPendingUpdate],
|
|
382
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
355
383
|
}).serialize());
|
|
356
384
|
ret.push(new files_1.ProtocolVirtualNodeMaskFile({
|
|
357
385
|
nodeIds: [...isVirtual],
|
|
386
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
358
387
|
}).serialize());
|
|
359
388
|
ret.push(new files_1.ProtocolPendingDiscoveryNodeMaskFile({
|
|
360
389
|
nodeIds: [...pendingDiscovery],
|
|
390
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
361
391
|
}).serialize());
|
|
362
392
|
// TODO: format >= 2: { .key = FILE_ID_LRANGE_NODE_EXIST, .size = FILE_SIZE_LRANGE_NODE_EXIST, .name = "LRANGE_NODE_EXIST"},
|
|
363
393
|
if (nvm.controller.preferredRepeaters?.length) {
|
|
364
394
|
ret.push(new files_1.ProtocolPreferredRepeatersFile({
|
|
365
395
|
nodeIds: nvm.controller.preferredRepeaters,
|
|
396
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
366
397
|
}).serialize());
|
|
367
398
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
399
|
+
if (nvm.format < 5) {
|
|
400
|
+
ret.push(new files_1.SUCUpdateEntriesFileV0({
|
|
401
|
+
updateEntries: nvm.controller.sucUpdateEntries,
|
|
402
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
403
|
+
}).serialize());
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
// V5 has split the SUC update entries into multiple files
|
|
407
|
+
for (let index = 0; index < consts_1.SUC_MAX_UPDATES; index += files_1.SUC_UPDATES_PER_FILE_V5) {
|
|
408
|
+
const slice = nvm.controller.sucUpdateEntries.slice(index, index + files_1.SUC_UPDATES_PER_FILE_V5);
|
|
409
|
+
if (slice.length === 0)
|
|
410
|
+
break;
|
|
411
|
+
const file = new files_1.SUCUpdateEntriesFileV5({
|
|
412
|
+
updateEntries: slice,
|
|
413
|
+
fileVersion: nvm.controller.protocolVersion,
|
|
414
|
+
});
|
|
415
|
+
file.fileId = (0, files_1.sucUpdateIndexToSUCUpdateEntriesFileIDV5)(index);
|
|
416
|
+
ret.push(file.serialize());
|
|
417
|
+
}
|
|
418
|
+
}
|
|
371
419
|
return ret;
|
|
372
420
|
}
|
|
373
|
-
function
|
|
421
|
+
function jsonToNVMObjects_v7_0_0(json, targetSDKVersion) {
|
|
374
422
|
const target = (0, safe_2.cloneDeep)(json);
|
|
423
|
+
target.controller.protocolVersion = "7.0.0";
|
|
375
424
|
target.format = 0;
|
|
425
|
+
target.controller.applicationVersion = targetSDKVersion.format();
|
|
376
426
|
const applicationObjects = new Map();
|
|
377
427
|
const protocolObjects = new Map();
|
|
378
428
|
const addApplicationObjects = (...objects) => {
|
|
@@ -386,21 +436,23 @@ function jsonToNVMObjects_v0(json, major, minor, patch) {
|
|
|
386
436
|
}
|
|
387
437
|
};
|
|
388
438
|
// Application files
|
|
389
|
-
const [applMajor, applMinor, applPatch] = target.controller.applicationVersion.split(".").map((i) => parseInt(i));
|
|
390
439
|
const applVersionFile = new files_1.ApplicationVersionFile({
|
|
391
|
-
format
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
440
|
+
// The SDK compares 4-byte values where the format is set to 0 to determine whether a migration is needed
|
|
441
|
+
format: 0,
|
|
442
|
+
major: targetSDKVersion.major,
|
|
443
|
+
minor: targetSDKVersion.minor,
|
|
444
|
+
patch: targetSDKVersion.patch,
|
|
445
|
+
fileVersion: target.controller.applicationVersion, // does not matter for this file
|
|
395
446
|
});
|
|
396
447
|
addApplicationObjects(applVersionFile.serialize());
|
|
397
448
|
addApplicationObjects(...serializeCommonApplicationObjects(target));
|
|
398
449
|
// Protocol files
|
|
399
450
|
const protocolVersionFile = new files_1.ProtocolVersionFile({
|
|
400
451
|
format: target.format,
|
|
401
|
-
major,
|
|
402
|
-
minor,
|
|
403
|
-
patch,
|
|
452
|
+
major: 7,
|
|
453
|
+
minor: 0,
|
|
454
|
+
patch: 0,
|
|
455
|
+
fileVersion: target.controller.protocolVersion, // does not matter for this file
|
|
404
456
|
});
|
|
405
457
|
addProtocolObjects(protocolVersionFile.serialize());
|
|
406
458
|
const nodeInfoFiles = new Map();
|
|
@@ -416,6 +468,7 @@ function jsonToNVMObjects_v0(json, major, minor, patch) {
|
|
|
416
468
|
const nodeInfoFileIndex = (0, files_1.nodeIdToNodeInfoFileIDV0)(nodeId);
|
|
417
469
|
nodeInfoFiles.set(nodeInfoFileIndex, new files_1.NodeInfoFileV0({
|
|
418
470
|
nodeInfo: nvmJSONNodeToNodeInfo(nodeId, node),
|
|
471
|
+
fileVersion: target.controller.protocolVersion,
|
|
419
472
|
}));
|
|
420
473
|
// Create/update route cache file (if there is a route)
|
|
421
474
|
if (node.lwr || node.nlwr) {
|
|
@@ -427,13 +480,18 @@ function jsonToNVMObjects_v0(json, major, minor, patch) {
|
|
|
427
480
|
lwr: node.lwr ?? (0, files_1.getEmptyRoute)(),
|
|
428
481
|
nlwr: node.nlwr ?? (0, files_1.getEmptyRoute)(),
|
|
429
482
|
},
|
|
483
|
+
fileVersion: target.controller.protocolVersion,
|
|
430
484
|
}));
|
|
431
485
|
}
|
|
432
486
|
}
|
|
433
487
|
addProtocolObjects(...serializeCommonProtocolObjects(target));
|
|
434
|
-
addProtocolObjects(new files_1.ProtocolNodeListFile({
|
|
488
|
+
addProtocolObjects(new files_1.ProtocolNodeListFile({
|
|
489
|
+
nodeIds: [...nodeInfoExists],
|
|
490
|
+
fileVersion: target.controller.protocolVersion,
|
|
491
|
+
}).serialize());
|
|
435
492
|
addProtocolObjects(new files_1.ProtocolRouteCacheExistsNodeMaskFile({
|
|
436
493
|
nodeIds: [...routeCacheExists],
|
|
494
|
+
fileVersion: target.controller.protocolVersion,
|
|
437
495
|
}).serialize());
|
|
438
496
|
if (nodeInfoFiles.size > 0) {
|
|
439
497
|
addProtocolObjects(...[...nodeInfoFiles.values()].map((f) => f.serialize()));
|
|
@@ -446,11 +504,47 @@ function jsonToNVMObjects_v0(json, major, minor, patch) {
|
|
|
446
504
|
protocolObjects,
|
|
447
505
|
};
|
|
448
506
|
}
|
|
449
|
-
exports.
|
|
450
|
-
function
|
|
507
|
+
exports.jsonToNVMObjects_v7_0_0 = jsonToNVMObjects_v7_0_0;
|
|
508
|
+
function jsonToNVMObjects_v7_11_0(json, targetSDKVersion) {
|
|
451
509
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
452
510
|
const target = (0, safe_2.cloneDeep)(json);
|
|
453
|
-
|
|
511
|
+
let targetApplicationVersion;
|
|
512
|
+
let targetProtocolVersion;
|
|
513
|
+
let targetProtocolFormat;
|
|
514
|
+
// We currently support application version migrations up to 7.19.1
|
|
515
|
+
// For all higher ones, set the highest version we support and let the controller handle the migration itself
|
|
516
|
+
if (semver_1.default.lte(targetSDKVersion, "7.19.1")) {
|
|
517
|
+
targetApplicationVersion = semver_1.default.parse(targetSDKVersion);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
targetApplicationVersion = semver_1.default.parse("7.19.1");
|
|
521
|
+
}
|
|
522
|
+
// The protocol version file only seems to be updated when the format of the protocol file system changes
|
|
523
|
+
// Once again, we simply set the highest version we support here and let the controller handle any potential migration
|
|
524
|
+
if (semver_1.default.gte(targetSDKVersion, "7.19.0")) {
|
|
525
|
+
targetProtocolVersion = semver_1.default.parse("7.19.0");
|
|
526
|
+
targetProtocolFormat = 5;
|
|
527
|
+
}
|
|
528
|
+
else if (semver_1.default.gte(targetSDKVersion, "7.17.0")) {
|
|
529
|
+
targetProtocolVersion = semver_1.default.parse("7.17.0");
|
|
530
|
+
targetProtocolFormat = 4;
|
|
531
|
+
}
|
|
532
|
+
else if (semver_1.default.gte(targetSDKVersion, "7.15.3")) {
|
|
533
|
+
targetProtocolVersion = semver_1.default.parse("7.15.3");
|
|
534
|
+
targetProtocolFormat = 3;
|
|
535
|
+
}
|
|
536
|
+
else if (semver_1.default.gte(targetSDKVersion, "7.12.0")) {
|
|
537
|
+
targetProtocolVersion = semver_1.default.parse("7.12.0");
|
|
538
|
+
targetProtocolFormat = 2;
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
// All versions below 7.11.0 are handled in the _v7_0_0 method
|
|
542
|
+
targetProtocolVersion = semver_1.default.parse("7.11.0");
|
|
543
|
+
targetProtocolFormat = 1;
|
|
544
|
+
}
|
|
545
|
+
target.format = targetProtocolFormat;
|
|
546
|
+
target.controller.applicationVersion = targetApplicationVersion.format();
|
|
547
|
+
target.controller.protocolVersion = targetProtocolVersion.format();
|
|
454
548
|
const applicationObjects = new Map();
|
|
455
549
|
const protocolObjects = new Map();
|
|
456
550
|
const addApplicationObjects = (...objects) => {
|
|
@@ -464,12 +558,13 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
464
558
|
}
|
|
465
559
|
};
|
|
466
560
|
// Application files
|
|
467
|
-
const [applMajor, applMinor, applPatch] = target.controller.applicationVersion.split(".").map((i) => parseInt(i));
|
|
468
561
|
const applVersionFile = new files_1.ApplicationVersionFile({
|
|
469
|
-
format
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
562
|
+
// The SDK compares 4-byte values where the format is set to 0 to determine whether a migration is needed
|
|
563
|
+
format: 0,
|
|
564
|
+
major: targetApplicationVersion.major,
|
|
565
|
+
minor: targetApplicationVersion.minor,
|
|
566
|
+
patch: targetApplicationVersion.patch,
|
|
567
|
+
fileVersion: target.controller.applicationVersion, // does not matter for this file
|
|
473
568
|
});
|
|
474
569
|
addApplicationObjects(applVersionFile.serialize());
|
|
475
570
|
// When converting it can be that the rfConfig doesn't exist. Make sure
|
|
@@ -481,19 +576,20 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
481
576
|
enablePTI: null,
|
|
482
577
|
maxTXPower: null,
|
|
483
578
|
});
|
|
484
|
-
//
|
|
485
|
-
//
|
|
486
|
-
if (
|
|
579
|
+
// Make sure the RF config format matches the application version.
|
|
580
|
+
// Otherwise, the controller will ignore the file and not accept any changes to the RF config
|
|
581
|
+
if (semver_1.default.gte(targetSDKVersion, "7.15.3")) {
|
|
487
582
|
(_b = target.controller.rfConfig).enablePTI ?? (_b.enablePTI = 0);
|
|
488
583
|
(_c = target.controller.rfConfig).maxTXPower ?? (_c.maxTXPower = 14.0);
|
|
489
584
|
}
|
|
490
585
|
addApplicationObjects(...serializeCommonApplicationObjects(target));
|
|
491
586
|
// Protocol files
|
|
492
587
|
const protocolVersionFile = new files_1.ProtocolVersionFile({
|
|
493
|
-
format:
|
|
494
|
-
major,
|
|
495
|
-
minor,
|
|
496
|
-
patch,
|
|
588
|
+
format: targetProtocolFormat,
|
|
589
|
+
major: targetProtocolVersion.major,
|
|
590
|
+
minor: targetProtocolVersion.minor,
|
|
591
|
+
patch: targetProtocolVersion.patch,
|
|
592
|
+
fileVersion: target.controller.protocolVersion, // does not matter for this file
|
|
497
593
|
});
|
|
498
594
|
addProtocolObjects(protocolVersionFile.serialize());
|
|
499
595
|
const nodeInfoFiles = new Map();
|
|
@@ -510,6 +606,7 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
510
606
|
if (!nodeInfoFiles.has(nodeInfoFileIndex)) {
|
|
511
607
|
nodeInfoFiles.set(nodeInfoFileIndex, new files_1.NodeInfoFileV1({
|
|
512
608
|
nodeInfos: [],
|
|
609
|
+
fileVersion: target.controller.protocolVersion,
|
|
513
610
|
}));
|
|
514
611
|
}
|
|
515
612
|
const nodeInfoFile = nodeInfoFiles.get(nodeInfoFileIndex);
|
|
@@ -521,6 +618,7 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
521
618
|
if (!routeCacheFiles.has(routeCacheFileIndex)) {
|
|
522
619
|
routeCacheFiles.set(routeCacheFileIndex, new files_1.RouteCacheFileV1({
|
|
523
620
|
routeCaches: [],
|
|
621
|
+
fileVersion: target.controller.protocolVersion,
|
|
524
622
|
}));
|
|
525
623
|
}
|
|
526
624
|
const routeCacheFile = routeCacheFiles.get(routeCacheFileIndex);
|
|
@@ -533,7 +631,7 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
533
631
|
}
|
|
534
632
|
// For v3+ targets, the ControllerInfoFile must contain the LongRange properties
|
|
535
633
|
// or the controller will ignore the file and not have a home ID
|
|
536
|
-
if (
|
|
634
|
+
if (targetProtocolFormat >= 3) {
|
|
537
635
|
(_d = target.controller).lastNodeIdLR ?? (_d.lastNodeIdLR = 255);
|
|
538
636
|
(_e = target.controller).maxNodeIdLR ?? (_e.maxNodeIdLR = 0);
|
|
539
637
|
(_f = target.controller).reservedIdLR ?? (_f.reservedIdLR = 0);
|
|
@@ -541,9 +639,13 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
541
639
|
(_h = target.controller).dcdcConfig ?? (_h.dcdcConfig = 255);
|
|
542
640
|
}
|
|
543
641
|
addProtocolObjects(...serializeCommonProtocolObjects(target));
|
|
544
|
-
addProtocolObjects(new files_1.ProtocolNodeListFile({
|
|
642
|
+
addProtocolObjects(new files_1.ProtocolNodeListFile({
|
|
643
|
+
nodeIds: [...nodeInfoExists],
|
|
644
|
+
fileVersion: target.controller.protocolVersion,
|
|
645
|
+
}).serialize());
|
|
545
646
|
addProtocolObjects(new files_1.ProtocolRouteCacheExistsNodeMaskFile({
|
|
546
647
|
nodeIds: [...routeCacheExists],
|
|
648
|
+
fileVersion: target.controller.protocolVersion,
|
|
547
649
|
}).serialize());
|
|
548
650
|
if (nodeInfoFiles.size > 0) {
|
|
549
651
|
addProtocolObjects(...[...nodeInfoFiles.values()].map((f) => f.serialize()));
|
|
@@ -556,7 +658,7 @@ function jsonToNVMObjects_v1_to_v4(format, json, major, minor, patch) {
|
|
|
556
658
|
protocolObjects,
|
|
557
659
|
};
|
|
558
660
|
}
|
|
559
|
-
exports.
|
|
661
|
+
exports.jsonToNVMObjects_v7_11_0 = jsonToNVMObjects_v7_11_0;
|
|
560
662
|
/** Reads an NVM buffer and returns its JSON representation */
|
|
561
663
|
function nvmToJSON(buffer, debugLogs = false) {
|
|
562
664
|
const nvm = (0, nvm_1.parseNVM)(buffer, debugLogs);
|
|
@@ -574,26 +676,17 @@ function nvm500ToJSON(buffer) {
|
|
|
574
676
|
}
|
|
575
677
|
exports.nvm500ToJSON = nvm500ToJSON;
|
|
576
678
|
/** Takes a JSON represented NVM and converts it to binary */
|
|
577
|
-
function jsonToNVM(json,
|
|
578
|
-
const parsedVersion = semver_1.default.parse(
|
|
679
|
+
function jsonToNVM(json, targetSDKVersion) {
|
|
680
|
+
const parsedVersion = semver_1.default.parse(targetSDKVersion);
|
|
579
681
|
if (!parsedVersion) {
|
|
580
|
-
throw new safe_1.ZWaveError(`Invalid
|
|
682
|
+
throw new safe_1.ZWaveError(`Invalid SDK version: ${targetSDKVersion}`, safe_1.ZWaveErrorCodes.Argument_Invalid);
|
|
581
683
|
}
|
|
582
684
|
let objects;
|
|
583
|
-
if (semver_1.default.gte(parsedVersion, "7.
|
|
584
|
-
objects =
|
|
585
|
-
}
|
|
586
|
-
else if (semver_1.default.gte(parsedVersion, "7.15.3")) {
|
|
587
|
-
objects = jsonToNVMObjects_v1_to_v4(3, json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
588
|
-
}
|
|
589
|
-
else if (semver_1.default.gte(parsedVersion, "7.12.0")) {
|
|
590
|
-
objects = jsonToNVMObjects_v1_to_v4(2, json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
591
|
-
}
|
|
592
|
-
else if (semver_1.default.gte(parsedVersion, "7.11.0")) {
|
|
593
|
-
objects = jsonToNVMObjects_v1_to_v4(1, json, parsedVersion.major, parsedVersion.minor, parsedVersion.patch);
|
|
685
|
+
if (semver_1.default.gte(parsedVersion, "7.11.0")) {
|
|
686
|
+
objects = jsonToNVMObjects_v7_11_0(json, parsedVersion);
|
|
594
687
|
}
|
|
595
688
|
else if (semver_1.default.gte(parsedVersion, "7.0.0")) {
|
|
596
|
-
objects =
|
|
689
|
+
objects = jsonToNVMObjects_v7_0_0(json, parsedVersion);
|
|
597
690
|
}
|
|
598
691
|
else {
|
|
599
692
|
throw new safe_1.ZWaveError("jsonToNVM cannot convert to a pre-7.0 NVM version. Use jsonToNVM500 instead.", safe_1.ZWaveErrorCodes.Argument_Invalid);
|
|
@@ -766,11 +859,14 @@ exports.json700To500 = json700To500;
|
|
|
766
859
|
function migrateNVM(sourceNVM, targetNVM) {
|
|
767
860
|
let source;
|
|
768
861
|
let target;
|
|
862
|
+
let sourceProtocolFileFormat;
|
|
863
|
+
let targetProtocolFileFormat;
|
|
769
864
|
try {
|
|
770
865
|
source = {
|
|
771
866
|
type: 700,
|
|
772
867
|
json: nvmToJSON(sourceNVM),
|
|
773
868
|
};
|
|
869
|
+
sourceProtocolFileFormat = source.json.format;
|
|
774
870
|
}
|
|
775
871
|
catch (e) {
|
|
776
872
|
if ((0, safe_1.isZWaveError)(e) && e.code === safe_1.ZWaveErrorCodes.NVM_InvalidFormat) {
|
|
@@ -780,6 +876,14 @@ function migrateNVM(sourceNVM, targetNVM) {
|
|
|
780
876
|
json: nvm500ToJSON(sourceNVM),
|
|
781
877
|
};
|
|
782
878
|
}
|
|
879
|
+
else if ((0, safe_1.isZWaveError)(e) &&
|
|
880
|
+
e.code === safe_1.ZWaveErrorCodes.NVM_NotSupported &&
|
|
881
|
+
(0, typeguards_1.isObject)(e.context) &&
|
|
882
|
+
typeof e.context.protocolFileFormat === "number") {
|
|
883
|
+
// This is a 700 series NVM, but the protocol version is not (yet) supported
|
|
884
|
+
source = { type: "unknown" };
|
|
885
|
+
sourceProtocolFileFormat = e.context.protocolFileFormat;
|
|
886
|
+
}
|
|
783
887
|
else {
|
|
784
888
|
source = { type: "unknown" };
|
|
785
889
|
}
|
|
@@ -789,6 +893,7 @@ function migrateNVM(sourceNVM, targetNVM) {
|
|
|
789
893
|
type: 700,
|
|
790
894
|
json: nvmToJSON(targetNVM),
|
|
791
895
|
};
|
|
896
|
+
targetProtocolFileFormat = target.json.format;
|
|
792
897
|
}
|
|
793
898
|
catch (e) {
|
|
794
899
|
if ((0, safe_1.isZWaveError)(e) && e.code === safe_1.ZWaveErrorCodes.NVM_InvalidFormat) {
|
|
@@ -798,19 +903,48 @@ function migrateNVM(sourceNVM, targetNVM) {
|
|
|
798
903
|
json: nvm500ToJSON(targetNVM),
|
|
799
904
|
};
|
|
800
905
|
}
|
|
906
|
+
else if ((0, safe_1.isZWaveError)(e) &&
|
|
907
|
+
e.code === safe_1.ZWaveErrorCodes.NVM_NotSupported &&
|
|
908
|
+
source.type === 700 &&
|
|
909
|
+
(0, typeguards_1.isObject)(e.context) &&
|
|
910
|
+
typeof e.context.protocolFileFormat === "number") {
|
|
911
|
+
// This is a 700 series NVM, but the protocol version is not (yet) supported
|
|
912
|
+
target = { type: "unknown" };
|
|
913
|
+
targetProtocolFileFormat = e.context.protocolFileFormat;
|
|
914
|
+
}
|
|
801
915
|
else {
|
|
802
916
|
target = { type: "unknown" };
|
|
803
917
|
}
|
|
804
918
|
}
|
|
805
919
|
// Short circuit if...
|
|
806
|
-
if (
|
|
920
|
+
if (target.type === "unknown" &&
|
|
921
|
+
targetProtocolFileFormat &&
|
|
922
|
+
targetProtocolFileFormat > consts_1.MAX_PROTOCOL_FILE_FORMAT &&
|
|
923
|
+
sourceProtocolFileFormat &&
|
|
924
|
+
sourceProtocolFileFormat <= targetProtocolFileFormat) {
|
|
925
|
+
// ...both the source and the target are 700 series, but at least the target uses an unsupported protocol version.
|
|
926
|
+
// We can be sure hwoever that the target can upgrade any 700 series NVM to its protocol version, as long as the
|
|
927
|
+
// source protocol version is not higher than the target's
|
|
928
|
+
return sourceNVM;
|
|
929
|
+
}
|
|
930
|
+
else if (source.type === 700 && target.type === 700) {
|
|
807
931
|
//... the source and target protocol versions are compatible without conversion
|
|
808
932
|
const sourceProtocolVersion = source.json.controller.protocolVersion;
|
|
809
933
|
const targetProtocolVersion = target.json.controller.protocolVersion;
|
|
934
|
+
// ... and the application version on the both is compatible with the respective protocol version
|
|
935
|
+
const sourceApplicationVersion = source.json.controller.applicationVersion;
|
|
936
|
+
const targetApplicationVersion = target.json.controller.applicationVersion;
|
|
810
937
|
// The 700 series firmware can automatically upgrade backups from a previous protocol version
|
|
811
938
|
// Not sure when that ability was added. To be on the safe side, allow it for 7.16+ which definitely supports it.
|
|
812
939
|
if (semver_1.default.gte(targetProtocolVersion, "7.16.0") &&
|
|
813
|
-
semver_1.default.gte(targetProtocolVersion, sourceProtocolVersion)
|
|
940
|
+
semver_1.default.gte(targetProtocolVersion, sourceProtocolVersion) &&
|
|
941
|
+
// the application version is updated on every update, protocol version only when the format changes
|
|
942
|
+
// so this is a good indicator if the NVMs are in a compatible state
|
|
943
|
+
semver_1.default.gte(targetApplicationVersion, targetProtocolVersion) &&
|
|
944
|
+
semver_1.default.gte(sourceApplicationVersion, sourceProtocolVersion) &&
|
|
945
|
+
// avoid preserving broken 255.x versions which appear on some controllers
|
|
946
|
+
semver_1.default.lt(sourceApplicationVersion, "255.0.0") &&
|
|
947
|
+
semver_1.default.lt(targetApplicationVersion, "255.0.0")) {
|
|
814
948
|
return sourceNVM;
|
|
815
949
|
}
|
|
816
950
|
}
|
|
@@ -829,6 +963,13 @@ function migrateNVM(sourceNVM, targetNVM) {
|
|
|
829
963
|
// TypeScript doesn't understand multi-variable narrowings (yet)
|
|
830
964
|
source = source;
|
|
831
965
|
target = target;
|
|
966
|
+
// Some 700 series NVMs have a strange 255.x application version - fix that first
|
|
967
|
+
if (target.type === 700 &&
|
|
968
|
+
semver_1.default.gte(target.json.controller.applicationVersion, "255.0.0")) {
|
|
969
|
+
// replace both with the protocol version
|
|
970
|
+
target.json.controller.applicationVersion =
|
|
971
|
+
target.json.controller.protocolVersion;
|
|
972
|
+
}
|
|
832
973
|
// In any case, preserve the application version of the target stick
|
|
833
974
|
source.json.controller.applicationVersion =
|
|
834
975
|
target.json.controller.applicationVersion;
|
|
@@ -850,7 +991,8 @@ function migrateNVM(sourceNVM, targetNVM) {
|
|
|
850
991
|
};
|
|
851
992
|
// The target is a different series, try to preserve the RF config of the target stick
|
|
852
993
|
json.controller.rfConfig = target.json.controller.rfConfig;
|
|
853
|
-
|
|
994
|
+
// 700 series distinguishes the NVM format by the application version
|
|
995
|
+
return jsonToNVM(json, target.json.controller.applicationVersion);
|
|
854
996
|
}
|
|
855
997
|
else if (source.type === 700 && target.type === 500) {
|
|
856
998
|
// We need to downgrade the source to 500 series
|
|
@@ -868,7 +1010,8 @@ function migrateNVM(sourceNVM, targetNVM) {
|
|
|
868
1010
|
...source.json,
|
|
869
1011
|
meta: target.json.meta,
|
|
870
1012
|
};
|
|
871
|
-
|
|
1013
|
+
// 700 series distinguishes the NVM format by the application version
|
|
1014
|
+
return jsonToNVM(json, target.json.controller.applicationVersion);
|
|
872
1015
|
}
|
|
873
1016
|
}
|
|
874
1017
|
exports.migrateNVM = migrateNVM;
|