motion-master-client 0.0.367 → 0.0.368
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/package.json +1 -1
- package/src/api.js +46 -25
- package/src/api.js.map +1 -1
- package/src/lib/motion-master-req-res-client.d.ts +79 -1
- package/src/lib/motion-master-req-res-client.js +244 -0
- package/src/lib/motion-master-req-res-client.js.map +1 -1
- package/src/lib/product.d.ts +14 -0
- package/src/lib/product.js +30 -1
- package/src/lib/product.js.map +1 -1
- package/src/lib/smm/40701_DEBUG_Update_V77.0.bin +0 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.0.d.ts +1 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.0.js +5 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.0.js.map +1 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.1.bin +0 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.1.d.ts +1 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.1.js +5 -0
- package/src/lib/smm/40701_DEBUG_Update_V77.1.js.map +1 -0
- package/src/lib/smm/40701_DEBUG_Update_V99.0.bin +0 -0
- package/src/lib/smm/40701_DEBUG_Update_V99.0.d.ts +1 -0
- package/src/lib/smm/40701_DEBUG_Update_V99.0.js +5 -0
- package/src/lib/smm/40701_DEBUG_Update_V99.0.js.map +1 -0
- package/src/lib/smm.d.ts +14 -0
- package/src/lib/smm.js +18 -1
- package/src/lib/smm.js.map +1 -1
- package/src/lib/types.d.ts +34 -0
|
@@ -3350,6 +3350,250 @@ class MotionMasterReqResClient {
|
|
|
3350
3350
|
(0, rxjs_1.defer)(() => this.triggerSmmRestart(deviceRef)));
|
|
3351
3351
|
return (0, rxjs_1.concat)(...observables).pipe((0, operators_1.last)());
|
|
3352
3352
|
}
|
|
3353
|
+
/**
|
|
3354
|
+
* Resolves whether an automated SMM software update is allowed for the specified device.
|
|
3355
|
+
*
|
|
3356
|
+
* This method evaluates the device and the provided firmware binary against a set of
|
|
3357
|
+
* preconditions required for automated installation. It returns a detailed
|
|
3358
|
+
* {@link SmmAutomatedUpdate} object describing each individual check result, which
|
|
3359
|
+
* can be used to give precise feedback to the user when automation is not possible.
|
|
3360
|
+
*
|
|
3361
|
+
* The automation is only permitted when **all** of the following conditions are met:
|
|
3362
|
+
* - The device is a recognized Somanet product (`isValidProduct`).
|
|
3363
|
+
* - The device belongs to the Circulo product family (`isCirculo`).
|
|
3364
|
+
* - The binary is encrypted (`isBinaryEncrypted`).
|
|
3365
|
+
* - The binary targets one of the supported SMM versions — v1.4 (260) or v2.56 (568) (`isAllowedBinaryVersion`).
|
|
3366
|
+
* - If targeting v2.56, the device SoC firmware version is ≥ 5.5.0 (`canInstallV256`).
|
|
3367
|
+
* - The device is running a legacy SMM firmware below v1.3, i.e. version < 259 (`isDeviceLw1`).
|
|
3368
|
+
*
|
|
3369
|
+
* If the device is not a recognized product, the method returns early with all flags set
|
|
3370
|
+
* to `false` and default zero values to avoid unnecessary device communication.
|
|
3371
|
+
*
|
|
3372
|
+
* @param deviceRef - A reference to the target device.
|
|
3373
|
+
* @param buffer - The SMM firmware binary to be installed, provided as a `Uint8Array`.
|
|
3374
|
+
* Its header is parsed to determine the target version and encryption status.
|
|
3375
|
+
*
|
|
3376
|
+
* @returns A promise that resolves to an {@link SmmAutomatedUpdate} object containing:
|
|
3377
|
+
* - `isValidProduct` — Whether the device maps to a known Somanet product.
|
|
3378
|
+
* - `isCirculo` — Whether the device belongs to the Circulo product family.
|
|
3379
|
+
* - `isCirculo7` — Whether the device is a Circulo 7.
|
|
3380
|
+
* - `isCirculo9` — Whether the device is a Circulo 9.
|
|
3381
|
+
* - `isDeviceLw1` — Whether the device SMM firmware is below v1.3 (version < 259).
|
|
3382
|
+
* - `isBinaryEncrypted` — Whether the provided firmware binary is encrypted.
|
|
3383
|
+
* - `isAllowedBinaryVersion` — Whether the binary targets a supported version (v1.4 or v2.56).
|
|
3384
|
+
* - `canInstallV256` — Whether v2.56 can be installed (requires SoC firmware ≥ 5.5.0).
|
|
3385
|
+
* - `isAutomationAllowed` — Whether all preconditions for automated update are satisfied.
|
|
3386
|
+
* - `allowedTargetSmmVersions` — The list of supported target SMM versions: `[260, 568]`.
|
|
3387
|
+
* - `deviceFirmwareVersion` — The SoC firmware version string read from the device (index `0x100a:0`).
|
|
3388
|
+
* - `deviceSmmVersion` — The current SMM firmware version as a raw integer.
|
|
3389
|
+
* - `binaryVersion` — The target SMM version encoded in the binary header.
|
|
3390
|
+
*/
|
|
3391
|
+
resolveSmmAutomatedUpdateConditions(deviceRef, buffer) {
|
|
3392
|
+
var _a, _b;
|
|
3393
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
3394
|
+
const device = yield (0, rxjs_1.lastValueFrom)(this.resolveDevice(deviceRef));
|
|
3395
|
+
const product = (0, product_1.findSomanetProductById)(device === null || device === void 0 ? void 0 : device.serialNumber);
|
|
3396
|
+
const isValidProduct = !!product;
|
|
3397
|
+
// v1.4 (no safe torque), v2.56 (safe torque)
|
|
3398
|
+
const allowedTargetSmmVersions = [260, 568];
|
|
3399
|
+
if (!isValidProduct) {
|
|
3400
|
+
return {
|
|
3401
|
+
isValidProduct: false,
|
|
3402
|
+
isDeviceLw1: false,
|
|
3403
|
+
isCirculo: false,
|
|
3404
|
+
isCirculo7: false,
|
|
3405
|
+
isCirculo9: false,
|
|
3406
|
+
isBinaryEncrypted: false,
|
|
3407
|
+
isAllowedBinaryVersion: false,
|
|
3408
|
+
canInstallV256: false,
|
|
3409
|
+
isAutomationAllowed: false,
|
|
3410
|
+
allowedTargetSmmVersions,
|
|
3411
|
+
deviceFirmwareVersion: 'v0.0.0',
|
|
3412
|
+
deviceSmmVersion: 0,
|
|
3413
|
+
isV990: false,
|
|
3414
|
+
isV770: false,
|
|
3415
|
+
isV771: false,
|
|
3416
|
+
binaryVersion: 0,
|
|
3417
|
+
deviceSupportsStreaming: false,
|
|
3418
|
+
};
|
|
3419
|
+
}
|
|
3420
|
+
const deviceSmmVersion = yield (0, rxjs_1.lastValueFrom)(this.readSmmFirmwareVersionAsNumber(deviceRef));
|
|
3421
|
+
const deviceFirmwareVersion = (yield this.upload(deviceRef, 0x100a, 0));
|
|
3422
|
+
const binaryHeader = (0, smm_1.parseSmmBinaryHeaders)(buffer);
|
|
3423
|
+
const binaryInformation = (0, smm_1.getInformationFromSmmFirmwareVersion)(binaryHeader.swVersion);
|
|
3424
|
+
// Allow installation of smm v2.56 only if device SoC firmware version is >=5.5.0
|
|
3425
|
+
const canInstallV256 = binaryHeader.swVersion === 568 ? semver.gte((_a = semver.coerce(deviceFirmwareVersion)) !== null && _a !== void 0 ? _a : '0.0.0', '5.5.0') : true;
|
|
3426
|
+
const isCirculo = product.family === 'Circulo';
|
|
3427
|
+
const isDeviceLw1 = deviceSmmVersion < 259; // <v1.3
|
|
3428
|
+
const isV990 = deviceSmmVersion === 25344;
|
|
3429
|
+
const isV770 = deviceSmmVersion === 19712;
|
|
3430
|
+
const isV771 = deviceSmmVersion === 19713;
|
|
3431
|
+
const isBinaryEncrypted = binaryInformation.isEncrypted;
|
|
3432
|
+
const isAllowedBinaryVersion = allowedTargetSmmVersions.includes(binaryInformation.version);
|
|
3433
|
+
const isCirculo7 = isCirculo && product.group === 'Circulo 7';
|
|
3434
|
+
const isCirculo9 = isCirculo && product.group === 'Circulo 9';
|
|
3435
|
+
const deviceSupportsStreaming = semver.gte((_b = semver.coerce(deviceFirmwareVersion)) !== null && _b !== void 0 ? _b : '0.0.0', '5.2.0');
|
|
3436
|
+
const isAutomationAllowed = isCirculo &&
|
|
3437
|
+
isBinaryEncrypted &&
|
|
3438
|
+
isAllowedBinaryVersion &&
|
|
3439
|
+
canInstallV256 &&
|
|
3440
|
+
(isDeviceLw1 || isV990 || isV770 || isV771); // Allow automation for devices on legacy firmware (lw1) or already on one of the intermediate versions (v99.0, v77.0, v77.1)
|
|
3441
|
+
return {
|
|
3442
|
+
isValidProduct,
|
|
3443
|
+
isDeviceLw1,
|
|
3444
|
+
isCirculo,
|
|
3445
|
+
isCirculo7,
|
|
3446
|
+
isCirculo9,
|
|
3447
|
+
isBinaryEncrypted,
|
|
3448
|
+
isAllowedBinaryVersion,
|
|
3449
|
+
canInstallV256,
|
|
3450
|
+
isAutomationAllowed,
|
|
3451
|
+
allowedTargetSmmVersions,
|
|
3452
|
+
deviceFirmwareVersion,
|
|
3453
|
+
deviceSmmVersion,
|
|
3454
|
+
isV990,
|
|
3455
|
+
isV770,
|
|
3456
|
+
isV771,
|
|
3457
|
+
binaryVersion: binaryInformation.version,
|
|
3458
|
+
deviceSupportsStreaming,
|
|
3459
|
+
};
|
|
3460
|
+
});
|
|
3461
|
+
}
|
|
3462
|
+
/**
|
|
3463
|
+
* Performs an automated, multi-step SMM software update to an encrypted firmware version on a Circulo device.
|
|
3464
|
+
*
|
|
3465
|
+
* Before installing the target binary, this method evaluates the device state by calling
|
|
3466
|
+
* {@link resolveSmmAutomatedUpdateConditions}. Based on the result, it determines which
|
|
3467
|
+
* sequence of intermediate firmware versions must be installed first to transition the device
|
|
3468
|
+
* from unencrypted to encrypted firmware.
|
|
3469
|
+
*
|
|
3470
|
+
* The installation sequence depends on the current SMM version and device group:
|
|
3471
|
+
* - **Legacy (< v1.3) + Circulo 7**: v99.0 → v77.0 → target
|
|
3472
|
+
* - **Legacy (< v1.3) + Circulo 9**: v99.0 → v77.1 → target
|
|
3473
|
+
* - **v99.0 + Circulo 7**: v77.0 → target
|
|
3474
|
+
* - **v99.0 + Circulo 9**: v77.1 → target
|
|
3475
|
+
* - **v77.0 or v77.1**: target only
|
|
3476
|
+
*
|
|
3477
|
+
* If the device does not support streaming, `commandTimeout` is automatically extended to 420,000 ms.
|
|
3478
|
+
*
|
|
3479
|
+
* @param deviceRef - Reference to the target device.
|
|
3480
|
+
* @param username - Username used for SMM authentication.
|
|
3481
|
+
* @param password - Password used for SMM authentication.
|
|
3482
|
+
* @param buffer - The target encrypted firmware binary as a `Uint8Array`.
|
|
3483
|
+
* @param crc - CRC32 checksum of the target firmware binary for integrity verification.
|
|
3484
|
+
* @param chunkSize - (Optional) Size of each data chunk transmitted per step, in bytes. Defaults to 1000.
|
|
3485
|
+
* @param commandTimeout - (Optional) Timeout for each OS command in ms. Automatically overridden to 420,000 ms
|
|
3486
|
+
* if the device does not support streaming. Defaults to 30,000 ms.
|
|
3487
|
+
* @param responsePollingInterval - (Optional) Polling interval for command responses in ms. Defaults to 1000 ms.
|
|
3488
|
+
* @param fsBufferReadWriteTimeout - (Optional) Timeout for fs-buffer read/write operations in ms. Defaults to 120,000 ms.
|
|
3489
|
+
*
|
|
3490
|
+
* @returns An `Observable<void>` that completes when the full installation sequence finishes successfully.
|
|
3491
|
+
*
|
|
3492
|
+
* @throws {Error} With message `'Unknown product. Cannot perform SMM software update.'` if the device
|
|
3493
|
+
* serial number does not map to a known Somanet product.
|
|
3494
|
+
* @throws {Error} With a descriptive message listing unmet preconditions if automation is not allowed —
|
|
3495
|
+
* e.g. the device is not a Circulo, the binary is not encrypted, the target version is
|
|
3496
|
+
* unsupported, the SoC firmware is below v5.5.0 (for SMM v2.56), or the device is
|
|
3497
|
+
* already on SMM v1.3+.
|
|
3498
|
+
* @throws {Error} If any individual firmware installation step fails during execution.
|
|
3499
|
+
*/
|
|
3500
|
+
updateSmmSoftwareToEncrypted(deviceRef, username, password, buffer, crc, chunkSize = 1000, commandTimeout = 30000, responsePollingInterval = 1000, fsBufferReadWriteTimeout = 120000) {
|
|
3501
|
+
return new rxjs_1.Observable((subscriber) => {
|
|
3502
|
+
(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
3503
|
+
/**
|
|
3504
|
+
* We must wrap the whole anonymous function body in try/catch so the subscriber (in `catch`)
|
|
3505
|
+
* knows when the error happens. Otherwise, the application will "explode" when the error occurs.
|
|
3506
|
+
*
|
|
3507
|
+
* Observable function is synchronous. When the error occurs, it will handle it via `error: (err) => {}`
|
|
3508
|
+
* function. Here, that is not the case. The anonymous function is asynchronous and will update the
|
|
3509
|
+
* subscriber only when we tell it to do so via `subscriber.<method>`. Error handling from the outside
|
|
3510
|
+
* will not pick-up the errors from here as this is "fire-and-forget" type of function.
|
|
3511
|
+
*
|
|
3512
|
+
* @example
|
|
3513
|
+
*
|
|
3514
|
+
* ```typescript
|
|
3515
|
+
* asyncHandler(async (req, res, next) => {
|
|
3516
|
+
* somePromiseThatRejects().then(...) // ← no await, no .catch()
|
|
3517
|
+
* // or a setTimeout, event emitter, etc.
|
|
3518
|
+
*
|
|
3519
|
+
* // handler finishes immediately
|
|
3520
|
+
})
|
|
3521
|
+
*/
|
|
3522
|
+
try {
|
|
3523
|
+
const automatedInstall = yield this.resolveSmmAutomatedUpdateConditions(deviceRef, buffer);
|
|
3524
|
+
if (!automatedInstall.isValidProduct) {
|
|
3525
|
+
subscriber.error(new Error('Unknown product. Cannot perform SMM software update.'));
|
|
3526
|
+
return;
|
|
3527
|
+
}
|
|
3528
|
+
let observables = [];
|
|
3529
|
+
if (automatedInstall.isAutomationAllowed) {
|
|
3530
|
+
const v990crc = 0xd1a3bb72;
|
|
3531
|
+
const v990Buffer = yield Promise.resolve().then(() => tslib_1.__importStar(require('./smm/40701_DEBUG_Update_V99.0'))).then((m) => Uint8Array.from(atob(m.smmBinaryV990), (c, _) => { var _a; return (_a = c.codePointAt(0)) !== null && _a !== void 0 ? _a : 0; }));
|
|
3532
|
+
const v770crc = 0xe290a20a;
|
|
3533
|
+
const v770Buffer = yield Promise.resolve().then(() => tslib_1.__importStar(require('./smm/40701_DEBUG_Update_V77.0'))).then((m) => Uint8Array.from(atob(m.smmBinaryV770), (c, _) => { var _a; return (_a = c.codePointAt(0)) !== null && _a !== void 0 ? _a : 0; }));
|
|
3534
|
+
const v771crc = 0xa4a11125;
|
|
3535
|
+
const v771Buffer = yield Promise.resolve().then(() => tslib_1.__importStar(require('./smm/40701_DEBUG_Update_V77.1'))).then((m) => Uint8Array.from(atob(m.smmBinaryV771), (c, _) => { var _a; return (_a = c.codePointAt(0)) !== null && _a !== void 0 ? _a : 0; }));
|
|
3536
|
+
const v990$ = (0, rxjs_1.defer)(() => this.updateSmmSoftware(deviceRef, username, password, new Uint8Array(v990Buffer), v990crc, chunkSize, commandTimeout, responsePollingInterval, fsBufferReadWriteTimeout));
|
|
3537
|
+
const v770$ = (0, rxjs_1.defer)(() => this.updateSmmSoftware(deviceRef, username, password, new Uint8Array(v770Buffer), v770crc, chunkSize, commandTimeout, responsePollingInterval, fsBufferReadWriteTimeout));
|
|
3538
|
+
const v771$ = (0, rxjs_1.defer)(() => this.updateSmmSoftware(deviceRef, username, password, new Uint8Array(v771Buffer), v771crc, chunkSize, commandTimeout, responsePollingInterval, fsBufferReadWriteTimeout));
|
|
3539
|
+
const userVersion$ = (0, rxjs_1.defer)(() => this.updateSmmSoftware(deviceRef, username, password, buffer, crc, chunkSize, commandTimeout, responsePollingInterval, fsBufferReadWriteTimeout));
|
|
3540
|
+
if (automatedInstall.isDeviceLw1) {
|
|
3541
|
+
if (automatedInstall.isCirculo7) {
|
|
3542
|
+
observables = [v990$, v770$, userVersion$];
|
|
3543
|
+
}
|
|
3544
|
+
else if (automatedInstall.isCirculo9) {
|
|
3545
|
+
observables = [v990$, v771$, userVersion$];
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
else if (automatedInstall.isV990) {
|
|
3549
|
+
if (automatedInstall.isCirculo7) {
|
|
3550
|
+
observables = [v770$, userVersion$];
|
|
3551
|
+
}
|
|
3552
|
+
else if (automatedInstall.isCirculo9) {
|
|
3553
|
+
observables = [v771$, userVersion$];
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
else if (automatedInstall.isV770 || automatedInstall.isV771) {
|
|
3557
|
+
observables = [userVersion$];
|
|
3558
|
+
}
|
|
3559
|
+
(0, rxjs_1.concat)(...observables).subscribe({
|
|
3560
|
+
next: () => {
|
|
3561
|
+
subscriber.next();
|
|
3562
|
+
},
|
|
3563
|
+
error: (err) => {
|
|
3564
|
+
subscriber.error(err);
|
|
3565
|
+
},
|
|
3566
|
+
complete: () => {
|
|
3567
|
+
subscriber.complete();
|
|
3568
|
+
},
|
|
3569
|
+
});
|
|
3570
|
+
}
|
|
3571
|
+
else {
|
|
3572
|
+
const reasons = [];
|
|
3573
|
+
if (!automatedInstall.isCirculo) {
|
|
3574
|
+
reasons.push('The device is not part of the Circulo family.');
|
|
3575
|
+
}
|
|
3576
|
+
if (!automatedInstall.isDeviceLw1) {
|
|
3577
|
+
reasons.push('The device SMM software version is not lower than 1.3.');
|
|
3578
|
+
}
|
|
3579
|
+
if (!automatedInstall.isBinaryEncrypted) {
|
|
3580
|
+
reasons.push('The SMM binary is not encrypted.');
|
|
3581
|
+
}
|
|
3582
|
+
if (!automatedInstall.isAllowedBinaryVersion) {
|
|
3583
|
+
reasons.push('The target SMM software version is not supported for encrypted update.');
|
|
3584
|
+
}
|
|
3585
|
+
if (!automatedInstall.canInstallV256) {
|
|
3586
|
+
reasons.push('The device firmware must be minimum v5.5.0 for installing SMM v2.56.');
|
|
3587
|
+
}
|
|
3588
|
+
subscriber.error(new Error(`The following conditions are not met for SMM software automated update: ${reasons.join(' ')}`));
|
|
3589
|
+
}
|
|
3590
|
+
}
|
|
3591
|
+
catch (err) {
|
|
3592
|
+
subscriber.error(err);
|
|
3593
|
+
}
|
|
3594
|
+
}))();
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3353
3597
|
/**
|
|
3354
3598
|
* Transmits SMM parameters to the specified device.
|
|
3355
3599
|
*
|