homey-lib 2.45.4 → 2.46.1
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/assets/app/schema.d.ts +39 -0
- package/assets/app/schema.json +136 -0
- package/helpers/index.js +10 -0
- package/index.js +1 -0
- package/lib/App/index.js +96 -15
- package/lib/Util/file.js +84 -0
- package/lib/Util/index.js +62 -0
- package/lib/Util/zigbee.js +225 -0
- package/package.json +1 -1
- package/types/assets/app/schema.d.ts +39 -0
- package/types/helpers/index.d.ts +1 -0
- package/types/helpers/index.d.ts.map +1 -1
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
- package/types/lib/App/index.d.ts.map +1 -1
- package/types/lib/Util/file.d.ts +27 -0
- package/types/lib/Util/file.d.ts.map +1 -0
- package/types/lib/Util/index.d.ts +53 -0
- package/types/lib/Util/index.d.ts.map +1 -1
- package/types/lib/Util/zigbee.d.ts +88 -0
- package/types/lib/Util/zigbee.d.ts.map +1 -0
- package/webpack/index.js +1 -1
- package/webpack.config.js +1 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
|
|
5
|
+
const OTA_FILE_IDENTIFIER = 0x0BEEF11E;
|
|
6
|
+
const OTA_HEADER_VERSION = 0x0100;
|
|
7
|
+
const OTA_MIN_HEADER_LENGTH = 56;
|
|
8
|
+
|
|
9
|
+
const FIELD_CONTROL_BITS = {
|
|
10
|
+
securityCredentialVersion: 1 << 0,
|
|
11
|
+
deviceSpecificFile: 1 << 1,
|
|
12
|
+
hardwareVersionsPresent: 1 << 2,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {object} ZigbeeOTAHeader
|
|
17
|
+
* @property {number} fileSize - File size in bytes.
|
|
18
|
+
* @property {number} fileIdentifier - OTA file identifier.
|
|
19
|
+
* @property {number} headerVersion - OTA header version.
|
|
20
|
+
* @property {number} headerLength - OTA header length in bytes.
|
|
21
|
+
* @property {number} fieldControl - Field control bitmask.
|
|
22
|
+
* @property {number} manufacturerCode - Manufacturer code.
|
|
23
|
+
* @property {number} imageType - Image type.
|
|
24
|
+
* @property {number} fileVersion - File version.
|
|
25
|
+
* @property {number} zigbeeStackVersion - Zigbee stack version.
|
|
26
|
+
* @property {string} headerString - Header string (ASCII).
|
|
27
|
+
* @property {number} totalImageSize - Total image size in bytes.
|
|
28
|
+
* @property {number} [securityCredentialVersion] - Security credential version.
|
|
29
|
+
* @property {string} [upgradeFileDestination] - Destination EUI64 hex string.
|
|
30
|
+
* @property {number} [minimumHardwareVersion] - Minimum hardware version.
|
|
31
|
+
* @property {number} [maximumHardwareVersion] - Maximum hardware version.
|
|
32
|
+
* @property {number} remainingHeaderBytes - Unparsed header bytes.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Read a fixed-length slice from the start of a file.
|
|
37
|
+
* @param {string} filePath - Absolute or relative path to the OTA file.
|
|
38
|
+
* @param {number} length - Number of bytes to read.
|
|
39
|
+
* @returns {Promise<Buffer>} Buffer with the requested bytes.
|
|
40
|
+
*/
|
|
41
|
+
async function readFileSlice(filePath, length) {
|
|
42
|
+
const fileHandle = await fs.promises.open(filePath, 'r');
|
|
43
|
+
try {
|
|
44
|
+
const buffer = Buffer.alloc(length);
|
|
45
|
+
const { bytesRead } = await fileHandle.read(buffer, 0, length, 0);
|
|
46
|
+
if (bytesRead < length) {
|
|
47
|
+
throw new Error('Unexpected end of file while reading Zigbee OTA header');
|
|
48
|
+
}
|
|
49
|
+
return buffer;
|
|
50
|
+
} finally {
|
|
51
|
+
await fileHandle.close();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Parse the Zigbee OTA header from a file.
|
|
57
|
+
* @param {string} filePath - Absolute or relative path to the OTA file.
|
|
58
|
+
* @returns {Promise<ZigbeeOTAHeader>} Parsed header values.
|
|
59
|
+
*/
|
|
60
|
+
async function parseZigbeeOTAHeader(filePath) {
|
|
61
|
+
if (typeof filePath !== 'string' || filePath.length === 0) {
|
|
62
|
+
throw new TypeError('filePath must be a non-empty string');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const stats = await fs.promises.stat(filePath);
|
|
66
|
+
if (stats.size < OTA_MIN_HEADER_LENGTH) {
|
|
67
|
+
throw new Error('File is too small to contain a Zigbee OTA header');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const baseHeader = await readFileSlice(filePath, OTA_MIN_HEADER_LENGTH);
|
|
71
|
+
const baseFileIdentifier = baseHeader.readUInt32LE(0);
|
|
72
|
+
|
|
73
|
+
if (baseFileIdentifier !== OTA_FILE_IDENTIFIER) {
|
|
74
|
+
throw new Error('Invalid Zigbee OTA header identifier');
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const headerLength = baseHeader.readUInt16LE(6);
|
|
78
|
+
|
|
79
|
+
if (headerLength < OTA_MIN_HEADER_LENGTH) {
|
|
80
|
+
throw new Error('Zigbee OTA header length is shorter than the mandatory header size');
|
|
81
|
+
}
|
|
82
|
+
if (headerLength > stats.size) {
|
|
83
|
+
throw new Error('Zigbee OTA header length exceeds file size');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const headerBuffer = headerLength === OTA_MIN_HEADER_LENGTH
|
|
87
|
+
? baseHeader
|
|
88
|
+
: await readFileSlice(filePath, headerLength);
|
|
89
|
+
|
|
90
|
+
let offset = 0;
|
|
91
|
+
const fileIdentifier = headerBuffer.readUInt32LE(offset);
|
|
92
|
+
offset += 4;
|
|
93
|
+
if (fileIdentifier !== OTA_FILE_IDENTIFIER) {
|
|
94
|
+
throw new Error('Invalid Zigbee OTA header identifier');
|
|
95
|
+
}
|
|
96
|
+
const headerVersion = headerBuffer.readUInt16LE(offset);
|
|
97
|
+
offset += 2;
|
|
98
|
+
const parsedHeaderLength = headerBuffer.readUInt16LE(offset);
|
|
99
|
+
offset += 2;
|
|
100
|
+
const fieldControl = headerBuffer.readUInt16LE(offset);
|
|
101
|
+
offset += 2;
|
|
102
|
+
const manufacturerCode = headerBuffer.readUInt16LE(offset);
|
|
103
|
+
offset += 2;
|
|
104
|
+
const imageType = headerBuffer.readUInt16LE(offset);
|
|
105
|
+
offset += 2;
|
|
106
|
+
const fileVersion = headerBuffer.readUInt32LE(offset);
|
|
107
|
+
offset += 4;
|
|
108
|
+
const zigbeeStackVersion = headerBuffer.readUInt16LE(offset);
|
|
109
|
+
offset += 2;
|
|
110
|
+
const headerString = headerBuffer
|
|
111
|
+
.toString('ascii', offset, offset + 32)
|
|
112
|
+
.replace(/\0+$/, '');
|
|
113
|
+
offset += 32;
|
|
114
|
+
const totalImageSize = headerBuffer.readUInt32LE(offset);
|
|
115
|
+
offset += 4;
|
|
116
|
+
|
|
117
|
+
const header = {
|
|
118
|
+
fileSize: stats.size,
|
|
119
|
+
fileIdentifier,
|
|
120
|
+
headerVersion,
|
|
121
|
+
headerLength: parsedHeaderLength,
|
|
122
|
+
fieldControl,
|
|
123
|
+
manufacturerCode,
|
|
124
|
+
imageType,
|
|
125
|
+
fileVersion,
|
|
126
|
+
zigbeeStackVersion,
|
|
127
|
+
headerString,
|
|
128
|
+
totalImageSize,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
if (fieldControl & FIELD_CONTROL_BITS.securityCredentialVersion) {
|
|
132
|
+
header.securityCredentialVersion = headerBuffer.readUInt8(offset);
|
|
133
|
+
offset += 1;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (fieldControl & FIELD_CONTROL_BITS.deviceSpecificFile) {
|
|
137
|
+
header.upgradeFileDestination = headerBuffer
|
|
138
|
+
.slice(offset, offset + 8)
|
|
139
|
+
.toString('hex');
|
|
140
|
+
offset += 8;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (fieldControl & FIELD_CONTROL_BITS.hardwareVersionsPresent) {
|
|
144
|
+
header.minimumHardwareVersion = headerBuffer.readUInt16LE(offset);
|
|
145
|
+
offset += 2;
|
|
146
|
+
header.maximumHardwareVersion = headerBuffer.readUInt16LE(offset);
|
|
147
|
+
offset += 2;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (parsedHeaderLength < offset) {
|
|
151
|
+
throw new Error('Zigbee OTA header length is shorter than parsed fields');
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
header.remainingHeaderBytes = parsedHeaderLength - offset;
|
|
155
|
+
|
|
156
|
+
return header;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Validate a Zigbee OTA header against expected values.
|
|
161
|
+
* @param {object} options - Validation options.
|
|
162
|
+
* @param {string} options.filePath - Absolute or relative path to the OTA file.
|
|
163
|
+
* @param {number} [options.manufacturerCode] - Expected manufacturer code.
|
|
164
|
+
* @param {number} [options.fileVersion] - Expected file version.
|
|
165
|
+
* @param {number} [options.imageType] - Expected image type.
|
|
166
|
+
* @returns {Promise<ZigbeeOTAHeader>} Parsed header values.
|
|
167
|
+
*/
|
|
168
|
+
async function validateZigbeeOTAHeader({
|
|
169
|
+
filePath,
|
|
170
|
+
manufacturerCode,
|
|
171
|
+
fileVersion,
|
|
172
|
+
imageType,
|
|
173
|
+
} = {}) {
|
|
174
|
+
const header = await parseZigbeeOTAHeader(filePath);
|
|
175
|
+
|
|
176
|
+
if (header.fileIdentifier !== OTA_FILE_IDENTIFIER) {
|
|
177
|
+
throw new Error('Invalid Zigbee OTA header identifier');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (header.headerVersion !== OTA_HEADER_VERSION) {
|
|
181
|
+
throw new Error('Unsupported Zigbee OTA header version');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (header.headerLength > header.totalImageSize) {
|
|
185
|
+
throw new Error('Zigbee OTA header length exceeds total image size');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (header.totalImageSize !== header.fileSize) {
|
|
189
|
+
throw new Error('Zigbee OTA total image size does not match file size');
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (manufacturerCode !== undefined) {
|
|
193
|
+
if (typeof manufacturerCode !== 'number') {
|
|
194
|
+
throw new TypeError('manufacturerCode must be a number');
|
|
195
|
+
}
|
|
196
|
+
if (header.manufacturerCode !== manufacturerCode) {
|
|
197
|
+
throw new Error('Zigbee OTA manufacturer code does not match');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (imageType !== undefined) {
|
|
202
|
+
if (typeof imageType !== 'number') {
|
|
203
|
+
throw new TypeError('imageType must be a number');
|
|
204
|
+
}
|
|
205
|
+
if (header.imageType !== imageType) {
|
|
206
|
+
throw new Error('Zigbee OTA image type does not match');
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (fileVersion !== undefined) {
|
|
211
|
+
if (typeof fileVersion !== 'number') {
|
|
212
|
+
throw new TypeError('fileVersion must be a number');
|
|
213
|
+
}
|
|
214
|
+
if (header.fileVersion !== fileVersion) {
|
|
215
|
+
throw new Error('Zigbee OTA file version does not match');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return header;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
module.exports = {
|
|
223
|
+
parseZigbeeOTAHeader,
|
|
224
|
+
validateZigbeeOTAHeader,
|
|
225
|
+
};
|
package/package.json
CHANGED
|
@@ -80,6 +80,7 @@ export type DriverSettings = (
|
|
|
80
80
|
[k: string]: unknown;
|
|
81
81
|
}
|
|
82
82
|
)[];
|
|
83
|
+
export type Integrity = string;
|
|
83
84
|
export type AppSettings = (
|
|
84
85
|
| {
|
|
85
86
|
type: "text" | "password" | "textarea" | "label";
|
|
@@ -247,6 +248,7 @@ export interface App {
|
|
|
247
248
|
[k: string]: unknown;
|
|
248
249
|
}[];
|
|
249
250
|
settings?: DriverSettings;
|
|
251
|
+
firmwareUpdates?: ZigbeeFirmwareUpdates;
|
|
250
252
|
gtin?: string | string[];
|
|
251
253
|
matter?: MatterDevice;
|
|
252
254
|
zwave?: ZwaveDevice;
|
|
@@ -373,6 +375,43 @@ export interface ZwaveSetting {
|
|
|
373
375
|
signed?: boolean;
|
|
374
376
|
[k: string]: unknown;
|
|
375
377
|
}
|
|
378
|
+
export interface ZigbeeFirmwareUpdates {
|
|
379
|
+
queryNextImageTimeout?: number;
|
|
380
|
+
minImageBlockPeriod?: number;
|
|
381
|
+
maxImageBlockSize?: number;
|
|
382
|
+
imageBlockRequestTimeout?: number;
|
|
383
|
+
upgradeEndRequestTimeout?: number;
|
|
384
|
+
upgradeEndDelay?: number;
|
|
385
|
+
postUpgradeAnnounceTimeout?: number;
|
|
386
|
+
/**
|
|
387
|
+
* @minItems 1
|
|
388
|
+
*/
|
|
389
|
+
updates: [ZigbeeFirmwareUpdate, ...ZigbeeFirmwareUpdate[]];
|
|
390
|
+
}
|
|
391
|
+
export interface ZigbeeFirmwareUpdate {
|
|
392
|
+
changelog: I18NObject;
|
|
393
|
+
device: ZigbeeFirmwareUpdateDevice;
|
|
394
|
+
/**
|
|
395
|
+
* @minItems 1
|
|
396
|
+
*/
|
|
397
|
+
files: [ZigbeeFirmwareUpdateFile, ...ZigbeeFirmwareUpdateFile[]];
|
|
398
|
+
}
|
|
399
|
+
export interface ZigbeeFirmwareUpdateDevice {
|
|
400
|
+
manufacturerName: string | string[];
|
|
401
|
+
productId: string | string[];
|
|
402
|
+
}
|
|
403
|
+
export interface ZigbeeFirmwareUpdateFile {
|
|
404
|
+
fileVersion: number;
|
|
405
|
+
imageType: number;
|
|
406
|
+
manufacturerCode: number;
|
|
407
|
+
minFileVersion?: number;
|
|
408
|
+
maxFileVersion?: number;
|
|
409
|
+
minHardwareVersion?: number;
|
|
410
|
+
maxHardwareVersion?: number;
|
|
411
|
+
size: number;
|
|
412
|
+
name: string;
|
|
413
|
+
integrity: Integrity;
|
|
414
|
+
}
|
|
376
415
|
export interface MatterDevice {
|
|
377
416
|
vendorId: number | number[];
|
|
378
417
|
productId: number | number[];
|
package/types/helpers/index.d.ts
CHANGED
|
@@ -7,5 +7,6 @@ export const readDirAsync: typeof fs.readdir.__promisify__;
|
|
|
7
7
|
export const lstatAsync: typeof fs.lstat.__promisify__;
|
|
8
8
|
export const imageSizeAsync: Function;
|
|
9
9
|
import fs = require("fs");
|
|
10
|
+
export function toArray(value: any): any[];
|
|
10
11
|
export { join, extname, basename, dirname };
|
|
11
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../helpers/index.js"],"names":[],"mappings":"wBAWe,4BAA4B;yBAE5B,6BAA6B;wBAE7B,4BAA4B;wBAE5B,4BAA4B;4BAE5B,gCAAgC;2BAEhC,+BAA+B;yBAE/B,6BAA6B"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../helpers/index.js"],"names":[],"mappings":"wBAWe,4BAA4B;yBAE5B,6BAA6B;wBAE7B,4BAA4B;wBAE5B,4BAA4B;4BAE5B,gCAAgC;2BAEhC,+BAA+B;yBAE/B,6BAA6B;;;AAkB5C,2CAMC"}
|
package/types/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export const getCurrencies: typeof Energy.getCurrencies;
|
|
|
12
12
|
export const getBatteries: typeof Energy.getBatteries;
|
|
13
13
|
export type AppManifest = import("./assets/app/schema").App;
|
|
14
14
|
export type CapabilityDefinition = import("./assets/capability/schema").Capability;
|
|
15
|
+
export type ZigbeeFirmwareUpdates = import("./assets/app/schema").ZigbeeFirmwareUpdates;
|
|
15
16
|
import App = require("./lib/App");
|
|
16
17
|
import Capability = require("./lib/Capability");
|
|
17
18
|
import Device = require("./lib/Device");
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.js"],"names":[],"mappings":"+BAkBW,OAAO,MAAM,CAAC,UAAU;6BAExB,OAAO,MAAM,CAAC,QAAQ;8BAGtB,OAAO,UAAU,CAAC,eAAe;4BAEjC,OAAO,UAAU,CAAC,aAAa;4BAE/B,OAAO,UAAU,CAAC,aAAa;4BAG/B,OAAO,GAAG,CAAC,UAAU;+BAErB,OAAO,GAAG,CAAC,aAAa;gCAExB,OAAO,GAAG,CAAC,cAAc;+BAEzB,OAAO,GAAG,CAAC,aAAa;6BAGxB,OAAO,KAAK,CAAC,SAAS;4BAGtB,OAAO,MAAM,CAAC,aAAa;2BAE3B,OAAO,MAAM,CAAC,YAAY;0BAGvB,OAAO,qBAAqB,EAAE,GAAG;mCACjC,OAAO,4BAA4B,EAAE,UAAU"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.js"],"names":[],"mappings":"+BAkBW,OAAO,MAAM,CAAC,UAAU;6BAExB,OAAO,MAAM,CAAC,QAAQ;8BAGtB,OAAO,UAAU,CAAC,eAAe;4BAEjC,OAAO,UAAU,CAAC,aAAa;4BAE/B,OAAO,UAAU,CAAC,aAAa;4BAG/B,OAAO,GAAG,CAAC,UAAU;+BAErB,OAAO,GAAG,CAAC,aAAa;gCAExB,OAAO,GAAG,CAAC,cAAc;+BAEzB,OAAO,GAAG,CAAC,aAAa;6BAGxB,OAAO,KAAK,CAAC,SAAS;4BAGtB,OAAO,MAAM,CAAC,aAAa;2BAE3B,OAAO,MAAM,CAAC,YAAY;0BAGvB,OAAO,qBAAqB,EAAE,GAAG;mCACjC,OAAO,4BAA4B,EAAE,UAAU;oCAC/C,OAAO,qBAAqB,EAAE,qBAAqB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/App/index.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/App/index.js"],"names":[],"mappings":";AA8EA;IACE,2CAAqD;IACrD,2CAAmD;IAmyBnD;;;OAGG;IACH,sCAHW,WAAW,GACT,IAAI,CAOhB;IA4PD;;;;;OAKG;IACH,4CALW,MAAM,QACN;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,aAClB,MAAM,GACJ,IAAI,CAkChB;IAiBD;;;OAGG;IACH,wBAHW,MAAM,GACJ,OAAO,CAQnB;IAED;;;OAGG;IACH,gCAHW,MAAM,GACJ,OAAO,CAInB;IAED;;OAEG;IACH,wBAFa,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAMnC;IAED;;OAEG;IACH,yBAFa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAcnD;IAED;;OAEG;IACH,wBAFa,MAAM,EAAE,CAIpB;IAED;;OAEG;IACH,qBAFa,MAAM,EAAE,CAKpB;IAED;;;OAGG;IACH,4BAHW,MAAM,GACJ,MAAM,CAuBlB;IAED;;;;OAIG;IACH,0BAJW,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,SAAS,WAC1C,WAAW,GACT,MAAM,GAAG,IAAI,CAyDzB;IAjvCD;;OAEG;IACH,kBAFW,MAAM,EAQhB;IALC,cAAiB;IAOnB;;;OAGG;IACH,eAHc,OAAO,EAAA,GACR,IAAI,CAKhB;IAED;;;OAGG;IACH,6BAHW;QAAE,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3D,OAAO,CAAC,IAAI,CAAC,CAywBzB;IAnwBC,gBAAmB;IAgxBrB;;;;OAIG;IACH,uCAJW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,UACvB;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GACZ,IAAI,CAwBhB;IAED;;;;OAIG;IACH,8BAJW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,WAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACxC,IAAI,CAuBhB;IAED;;;OAGG;IACH,gCAHW,MAAM,GACJ,OAAO,CAAC,MAAM,EAAE,CAAC,CAY7B;IAED;;;OAGG;IACH,yCAHW,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAOzB;IAED;;;OAGG;IACH,mCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAe5B;IAED;;;;;OAKG;IACH,2BALW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,QAChC,KAAK,GAAG,QAAQ,cAChB,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CA6BzB;IAED;;OAEG;IACH,oBAFa,OAAO,CAAC,IAAI,CAAC,CAuBzB;IAED;;;;;;OAMG;IACH,wBANW,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,aACvB,MAAM,WACN,WAAW,mCACX;QAAE,YAAY,EAAE,OAAO,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,GAC/C,IAAI,CA+EhB;IA0CD;;;;OAIG;IACH,qBAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAU3B;CAwJF;;;;mBAnyCa,OAAO,yBAAyB,EAAE,GAAG"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate a hex hash for the contents of a file.
|
|
3
|
+
* @param {string} filePath - Absolute or relative path to the file.
|
|
4
|
+
* @param {string} [hashName='sha256'] - Hash algorithm name (e.g. sha256).
|
|
5
|
+
* @returns {Promise<string>} Resolves with a hex-encoded digest.
|
|
6
|
+
*/
|
|
7
|
+
export function hashFile(filePath: string, hashName?: string): Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Create an integrity string for a file using an allowed hash algorithm.
|
|
10
|
+
* @param {string} filePath - Absolute or relative path to the file.
|
|
11
|
+
* @param {string} [hashName='sha256'] - Allowed hash algorithm name.
|
|
12
|
+
* @returns {Promise<string>} Resolves with `hashName:hexDigest`.
|
|
13
|
+
*/
|
|
14
|
+
export function getIntegrity(filePath: string, hashName?: string): Promise<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Validate file integrity using a `hashName:hexDigest` string.
|
|
17
|
+
* @param {string} filePath - Absolute or relative path to the file.
|
|
18
|
+
* @param {string} integrity - Hash name and hex digest separated by `:`.
|
|
19
|
+
* @returns {Promise<boolean>} Resolves with true when hashes match.
|
|
20
|
+
*/
|
|
21
|
+
export function validateIntegrity(filePath: string, integrity: string): Promise<boolean>;
|
|
22
|
+
export function getOTAFilePath({ appPath, driverId, fileName }: {
|
|
23
|
+
appPath: any;
|
|
24
|
+
driverId: any;
|
|
25
|
+
fileName: any;
|
|
26
|
+
}): string;
|
|
27
|
+
//# sourceMappingURL=file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../../lib/Util/file.js"],"names":[],"mappings":"AAkBA;;;;;GAKG;AACH,mCAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAW3B;AAwBD;;;;;GAKG;AACH,uCAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAW3B;AArCD;;;;;GAKG;AACH,4CAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAgB5B;AAmBD;;;;WAEC"}
|
|
@@ -11,6 +11,59 @@ declare class Util {
|
|
|
11
11
|
* @returns {string[]}
|
|
12
12
|
*/
|
|
13
13
|
static getMissingPlatformLocalFeatures(modelId: string, wantedFeatures: string[]): string[];
|
|
14
|
+
/**
|
|
15
|
+
* Create an integrity string for a file using an allowed hash algorithm.
|
|
16
|
+
* NOTE: This method is only available in Node.js environments.
|
|
17
|
+
* @param {string} filePath - Absolute or relative path to the file.
|
|
18
|
+
* @param {string} hashName - Allowed hash algorithm name.
|
|
19
|
+
* @returns {Promise<string>} Resolves with `hashName:hexDigest`.
|
|
20
|
+
*/
|
|
21
|
+
static getIntegrity(filePath: string, hashName: string): Promise<string>;
|
|
22
|
+
/**
|
|
23
|
+
* Validate file integrity using a `hashName:hexDigest` string.
|
|
24
|
+
* NOTE: This method is only available in Node.js environments.
|
|
25
|
+
* @param {string} filePath - Absolute or relative path to the file.
|
|
26
|
+
* @param {string} integrity - Hash name and hex digest separated by `:`.
|
|
27
|
+
* @returns {Promise<boolean>} Resolves with true when hashes match.
|
|
28
|
+
*/
|
|
29
|
+
static validateIntegrity(filePath: string, integrity: string): Promise<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* Parse the Zigbee OTA header from a file.
|
|
32
|
+
* NOTE: This method is only available in Node.js environments.
|
|
33
|
+
* @param {string} filePath - Absolute or relative path to the OTA file.
|
|
34
|
+
* @returns {Promise<import('./zigbee').ZigbeeOTAHeader>} Parsed header values.
|
|
35
|
+
*/
|
|
36
|
+
static parseZigbeeOTAHeader(filePath: string): Promise<import("./zigbee").ZigbeeOTAHeader>;
|
|
37
|
+
/**
|
|
38
|
+
* Validate a Zigbee OTA header against expected values.
|
|
39
|
+
* NOTE: This method is only available in Node.js environments.
|
|
40
|
+
* @param {object} options - Validation options.
|
|
41
|
+
* @param {string} options.filePath - Absolute or relative path to the OTA file.
|
|
42
|
+
* @param {number} [options.manufacturerCode] - Expected manufacturer code.
|
|
43
|
+
* @param {number} [options.fileVersion] - Expected file version.
|
|
44
|
+
* @param {number} [options.imageType] - Expected image type.
|
|
45
|
+
* @returns {Promise<import('./zigbee').ZigbeeOTAHeader>} Parsed header values.
|
|
46
|
+
*/
|
|
47
|
+
static validateZigbeeOTAHeader(options: {
|
|
48
|
+
filePath: string;
|
|
49
|
+
manufacturerCode?: number;
|
|
50
|
+
fileVersion?: number;
|
|
51
|
+
imageType?: number;
|
|
52
|
+
}): Promise<import("./zigbee").ZigbeeOTAHeader>;
|
|
53
|
+
/**
|
|
54
|
+
* Returns the expected file path for an OTA file based on app path, driver ID and file name.
|
|
55
|
+
* NOTE: This method is only available in Node.js environments.
|
|
56
|
+
* @param {object} options - File path options.
|
|
57
|
+
* @param {string} options.appPath - Absolute path to the app.
|
|
58
|
+
* @param {string} options.driverId - Driver ID.
|
|
59
|
+
* @param {string} options.fileName - OTA file name.
|
|
60
|
+
* @returns {string} Resolves with the expected file path.
|
|
61
|
+
*/
|
|
62
|
+
static getOTAFilePath({ appPath, driverId, fileName }: {
|
|
63
|
+
appPath: string;
|
|
64
|
+
driverId: string;
|
|
65
|
+
fileName: string;
|
|
66
|
+
}): string;
|
|
14
67
|
}
|
|
15
68
|
declare namespace Util {
|
|
16
69
|
let FEATURE_SPEAKER: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/Util/index.js"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../lib/Util/index.js"],"names":[],"mappings":";AAKA;IAEE;;;OAGG;IACH,yCAHW,MAAM,GACJ,MAAM,EAAE,CAIpB;IAED;;;;OAIG;IACH,gDAJW,MAAM,kBACN,MAAM,EAAE,GACN,MAAM,EAAE,CAKpB;IAED;;;;;;OAMG;IACH,8BAJW,MAAM,YACN,MAAM,GACJ,OAAO,CAAC,MAAM,CAAC,CAI3B;IAED;;;;;;OAMG;IACH,mCAJW,MAAM,aACN,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAI5B;IAED;;;;;OAKG;IACH,sCAHW,MAAM,GACJ,OAAO,CAAC,OAAO,UAAU,EAAE,eAAe,CAAC,CAIvD;IAED;;;;;;;;;OASG;IACH,wCANG;QAAwB,QAAQ,EAAxB,MAAM;QACW,gBAAgB,GAAjC,MAAM;QACW,WAAW,GAA5B,MAAM;QACW,SAAS,GAA1B,MAAM;KACd,GAAU,OAAO,CAAC,OAAO,UAAU,EAAE,eAAe,CAAC,CAIvD;IAED;;;;;;;;OAQG;IACH,uDALG;QAAwB,OAAO,EAAvB,MAAM;QACU,QAAQ,EAAxB,MAAM;QACU,QAAQ,EAAxB,MAAM;KACd,GAAU,MAAM,CAIlB;CAEF;;;;;;;gCAOU,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export type ZigbeeOTAHeader = {
|
|
2
|
+
/**
|
|
3
|
+
* - File size in bytes.
|
|
4
|
+
*/
|
|
5
|
+
fileSize: number;
|
|
6
|
+
/**
|
|
7
|
+
* - OTA file identifier.
|
|
8
|
+
*/
|
|
9
|
+
fileIdentifier: number;
|
|
10
|
+
/**
|
|
11
|
+
* - OTA header version.
|
|
12
|
+
*/
|
|
13
|
+
headerVersion: number;
|
|
14
|
+
/**
|
|
15
|
+
* - OTA header length in bytes.
|
|
16
|
+
*/
|
|
17
|
+
headerLength: number;
|
|
18
|
+
/**
|
|
19
|
+
* - Field control bitmask.
|
|
20
|
+
*/
|
|
21
|
+
fieldControl: number;
|
|
22
|
+
/**
|
|
23
|
+
* - Manufacturer code.
|
|
24
|
+
*/
|
|
25
|
+
manufacturerCode: number;
|
|
26
|
+
/**
|
|
27
|
+
* - Image type.
|
|
28
|
+
*/
|
|
29
|
+
imageType: number;
|
|
30
|
+
/**
|
|
31
|
+
* - File version.
|
|
32
|
+
*/
|
|
33
|
+
fileVersion: number;
|
|
34
|
+
/**
|
|
35
|
+
* - Zigbee stack version.
|
|
36
|
+
*/
|
|
37
|
+
zigbeeStackVersion: number;
|
|
38
|
+
/**
|
|
39
|
+
* - Header string (ASCII).
|
|
40
|
+
*/
|
|
41
|
+
headerString: string;
|
|
42
|
+
/**
|
|
43
|
+
* - Total image size in bytes.
|
|
44
|
+
*/
|
|
45
|
+
totalImageSize: number;
|
|
46
|
+
/**
|
|
47
|
+
* - Security credential version.
|
|
48
|
+
*/
|
|
49
|
+
securityCredentialVersion?: number;
|
|
50
|
+
/**
|
|
51
|
+
* - Destination EUI64 hex string.
|
|
52
|
+
*/
|
|
53
|
+
upgradeFileDestination?: string;
|
|
54
|
+
/**
|
|
55
|
+
* - Minimum hardware version.
|
|
56
|
+
*/
|
|
57
|
+
minimumHardwareVersion?: number;
|
|
58
|
+
/**
|
|
59
|
+
* - Maximum hardware version.
|
|
60
|
+
*/
|
|
61
|
+
maximumHardwareVersion?: number;
|
|
62
|
+
/**
|
|
63
|
+
* - Unparsed header bytes.
|
|
64
|
+
*/
|
|
65
|
+
remainingHeaderBytes: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Parse the Zigbee OTA header from a file.
|
|
69
|
+
* @param {string} filePath - Absolute or relative path to the OTA file.
|
|
70
|
+
* @returns {Promise<ZigbeeOTAHeader>} Parsed header values.
|
|
71
|
+
*/
|
|
72
|
+
export function parseZigbeeOTAHeader(filePath: string): Promise<ZigbeeOTAHeader>;
|
|
73
|
+
/**
|
|
74
|
+
* Validate a Zigbee OTA header against expected values.
|
|
75
|
+
* @param {object} options - Validation options.
|
|
76
|
+
* @param {string} options.filePath - Absolute or relative path to the OTA file.
|
|
77
|
+
* @param {number} [options.manufacturerCode] - Expected manufacturer code.
|
|
78
|
+
* @param {number} [options.fileVersion] - Expected file version.
|
|
79
|
+
* @param {number} [options.imageType] - Expected image type.
|
|
80
|
+
* @returns {Promise<ZigbeeOTAHeader>} Parsed header values.
|
|
81
|
+
*/
|
|
82
|
+
export function validateZigbeeOTAHeader({ filePath, manufacturerCode, fileVersion, imageType, }?: {
|
|
83
|
+
filePath: string;
|
|
84
|
+
manufacturerCode?: number;
|
|
85
|
+
fileVersion?: number;
|
|
86
|
+
imageType?: number;
|
|
87
|
+
}): Promise<ZigbeeOTAHeader>;
|
|
88
|
+
//# sourceMappingURL=zigbee.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"zigbee.d.ts","sourceRoot":"","sources":["../../../lib/Util/zigbee.js"],"names":[],"mappings":";;;;cAgBc,MAAM;;;;oBACN,MAAM;;;;mBACN,MAAM;;;;kBACN,MAAM;;;;kBACN,MAAM;;;;sBACN,MAAM;;;;eACN,MAAM;;;;iBACN,MAAM;;;;wBACN,MAAM;;;;kBACN,MAAM;;;;oBACN,MAAM;;;;gCACN,MAAM;;;;6BACN,MAAM;;;;6BACN,MAAM;;;;6BACN,MAAM;;;;0BACN,MAAM;;AAuBpB;;;;GAIG;AACH,+CAHW,MAAM,GACJ,OAAO,CAAC,eAAe,CAAC,CAmGpC;AAED;;;;;;;;GAQG;AACH,kGANG;IAAwB,QAAQ,EAAxB,MAAM;IACW,gBAAgB,GAAjC,MAAM;IACW,WAAW,GAA5B,MAAM;IACW,SAAS,GAA1B,MAAM;CACd,GAAU,OAAO,CAAC,eAAe,CAAC,CAsDpC"}
|