UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

127 lines 27 kB
import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { InventoryService, OperationStatus } from '@c8y/client'; import { ServiceRegistry } from '@c8y/ngx-components'; import { RepositoryService, RepositoryType } from '@c8y/ngx-components/repository/shared'; import { head } from 'lodash-es'; import { BehaviorSubject, of } from 'rxjs'; import { filter, map, switchMap, take } from 'rxjs/operators'; import { DeviceSoftwareService } from './device-software.service'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "@c8y/ngx-components/repository/shared"; import * as i3 from "@c8y/client"; import * as i4 from "./device-software.service"; import * as i5 from "@c8y/ngx-components"; import * as i6 from "@angular/common"; import * as i7 from "./installed-software.component"; import * as i8 from "./device-software-changes.component"; export class SoftwareDeviceTabComponent { constructor(route, repository, inventory, deviceSoftwareService, serviceRegistry) { this.route = route; this.repository = repository; this.inventory = inventory; this.deviceSoftwareService = deviceSoftwareService; this.serviceRegistry = serviceRegistry; this.deviceId = this.route.snapshot.parent.data.contextData.id; this.device$ = new BehaviorSubject(this.route.snapshot.parent.data.contextData); this.typesQuery$ = this.device$.pipe(map(device => { const deviceTypeQuery = this.repository.getDeviceTypeQuery(RepositoryType.SOFTWARE, device); return this.repository.getSoftwareTypeQuery(device, deviceTypeQuery); })); this.changes$ = new BehaviorSubject([]); this.changesOperation$ = new BehaviorSubject(null); this.changesInProgress$ = this.changesOperation$.pipe(map(operation => this.isInProgress(operation))); this.reloading = false; this.showSoftwareChanges = false; } async ngOnInit() { const advancedSoftwareService = head(this.serviceRegistry.get('asm')); this.list$ = this.device$.pipe(switchMap(device => advancedSoftwareService ? advancedSoftwareService .isASMAvailable() .then(isASMAvailable => ({ isASMAvailable, device })) : of({ isASMAvailable: false, device })), map(({ isASMAvailable, device }) => // with ASM available software items will be retrieved directly in the // device-software-list component isASMAvailable ? undefined : this.repository.getDeviceSoftwareList(device))); await this.loadDevice(); await this.loadOperation(); } addChanges(requestedChanges) { let stagedChanges = [...this.changes$.value]; requestedChanges.forEach(requestedChange => { const alreadyStaged = stagedChanges.some(stagedChange => this.areSameChanges(stagedChange, requestedChange)); if (!alreadyStaged) { stagedChanges = [...stagedChanges, requestedChange]; } }); this.changes$.next(stagedChanges); } dropChange(changeToBeDropped) { let stagedChanges = [...this.changes$.value]; stagedChanges = stagedChanges.filter(stagedChange => !this.areSameChanges(stagedChange, changeToBeDropped)); this.changes$.next(stagedChanges); } areSameChanges(change1, change2) { return (change1.name === change2.name && change1.version === change2.version && change1.action === change2.action); } clearChanges() { this.changes$.next([]); } async loadDevice() { this.reloading = true; this.deviceSoftwareService.reload(); const device = await Promise.all([ this.deviceSoftwareService.loading$ .pipe(filter(loading => !loading), take(1)) .toPromise(), this.inventory.detail(this.deviceId, { withChildren: false }).then(result => result.data) ]).then(([_, device]) => device); this.device$.next(device); this.reloading = false; } async applyChanges() { const operation = await this.repository.createSoftwareUpdateOperation(this.device$.value, this.changes$.value); await this.trackOperation(operation); } async loadOperation() { const operation = await this.repository.getLastSoftwareUpdateOperation(this.deviceId); await this.trackOperation(operation); } async trackOperation(operation) { if ([OperationStatus.SUCCESSFUL, OperationStatus.FAILED].includes(operation?.status)) { this.changesOperation$.next(undefined); } else this.changesOperation$.next(operation); if (this.isInProgress(operation)) { await this.displayChangesFromOperation(operation); this.repository.observeOperation(operation).subscribe(operationUpdate => { this.changesOperation$.next(operationUpdate); if (operationUpdate.status === OperationStatus.SUCCESSFUL) { this.clearChanges(); this.loadDevice(); } }, operationUpdate => { this.changesOperation$.next(operationUpdate); }); } } async displayChangesFromOperation(operation) { const changes = await this.repository.getDeviceSoftwareChangesFromOperation(operation, this.device$.value); this.changes$.next(changes); } isInProgress(operation) { return (operation && [OperationStatus.PENDING, OperationStatus.EXECUTING].includes(operation.status)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SoftwareDeviceTabComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.RepositoryService }, { token: i3.InventoryService }, { token: i4.DeviceSoftwareService }, { token: i5.ServiceRegistry }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SoftwareDeviceTabComponent, selector: "c8y-software-device-tab", ngImport: i0, template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"loadDevice()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"card split-view--7-5 m-b-0\">\n <c8y-installed-software\n class=\"split-view__list\"\n [device]=\"device$ | async\"\n [typesQuery]=\"typesQuery$ | async\"\n [softwareList]=\"list$ | async\"\n [deviceSoftwareChanges]=\"changes$ | async\"\n [deviceSoftwareChangesInProgress]=\"changesInProgress$ | async\"\n (changes)=\"addChanges($event)\"\n (showSoftwareChanges)=\"showSoftwareChanges = true\"\n ></c8y-installed-software>\n <c8y-device-software-changes\n class=\"bg-level-1 split-view__detail\"\n [ngClass]=\"{ 'split-view__detail--selected': showSoftwareChanges }\"\n [deviceSoftwareChangesOperation]=\"changesOperation$ | async\"\n [changes]=\"changes$ | async\"\n [changesInProgress]=\"changesInProgress$ | async\"\n (clear)=\"clearChanges()\"\n (drop)=\"dropChange($event)\"\n (apply)=\"applyChanges()\"\n (hideSoftwareChanges)=\"showSoftwareChanges = false\"\n ></c8y-device-software-changes>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i5.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: i5.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: i7.InstalledSoftwareComponent, selector: "c8y-installed-software", inputs: ["device", "softwareList", "deviceSoftwareChanges", "deviceSoftwareChangesInProgress", "typesQuery"], outputs: ["changes", "showSoftwareChanges"] }, { kind: "component", type: i8.DeviceSoftwareChangesComponent, selector: "c8y-device-software-changes", inputs: ["changes", "changesInProgress", "deviceSoftwareChangesOperation"], outputs: ["clear", "drop", "apply", "hideSoftwareChanges"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SoftwareDeviceTabComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-software-device-tab', template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"loadDevice()\"\n >\n <i\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': reloading }\"\n ></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"card split-view--7-5 m-b-0\">\n <c8y-installed-software\n class=\"split-view__list\"\n [device]=\"device$ | async\"\n [typesQuery]=\"typesQuery$ | async\"\n [softwareList]=\"list$ | async\"\n [deviceSoftwareChanges]=\"changes$ | async\"\n [deviceSoftwareChangesInProgress]=\"changesInProgress$ | async\"\n (changes)=\"addChanges($event)\"\n (showSoftwareChanges)=\"showSoftwareChanges = true\"\n ></c8y-installed-software>\n <c8y-device-software-changes\n class=\"bg-level-1 split-view__detail\"\n [ngClass]=\"{ 'split-view__detail--selected': showSoftwareChanges }\"\n [deviceSoftwareChangesOperation]=\"changesOperation$ | async\"\n [changes]=\"changes$ | async\"\n [changesInProgress]=\"changesInProgress$ | async\"\n (clear)=\"clearChanges()\"\n (drop)=\"dropChange($event)\"\n (apply)=\"applyChanges()\"\n (hideSoftwareChanges)=\"showSoftwareChanges = false\"\n ></c8y-device-software-changes>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.RepositoryService }, { type: i3.InventoryService }, { type: i4.DeviceSoftwareService }, { type: i5.ServiceRegistry }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29mdHdhcmUtZGV2aWNlLXRhYi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L3NvZnR3YXJlL2RldmljZS10YWIvc29mdHdhcmUtZGV2aWNlLXRhYi5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L3NvZnR3YXJlL2RldmljZS10YWIvc29mdHdhcmUtZGV2aWNlLXRhYi5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRCxPQUFPLEVBQThCLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1RixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUlMLGlCQUFpQixFQUNqQixjQUFjLEVBQ2YsTUFBTSx1Q0FBdUMsQ0FBQztBQUMvQyxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2pDLE9BQU8sRUFBRSxlQUFlLEVBQWMsRUFBRSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQzs7Ozs7Ozs7OztBQU1sRSxNQUFNLE9BQU8sMEJBQTBCO0lBa0JyQyxZQUNVLEtBQXFCLEVBQ3JCLFVBQTZCLEVBQzdCLFNBQTJCLEVBQzNCLHFCQUE0QyxFQUM1QyxlQUFnQztRQUpoQyxVQUFLLEdBQUwsS0FBSyxDQUFnQjtRQUNyQixlQUFVLEdBQVYsVUFBVSxDQUFtQjtRQUM3QixjQUFTLEdBQVQsU0FBUyxDQUFrQjtRQUMz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U0FBUzsrQkFDRSx5QkFBeUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgSU1hbmFnZWRPYmplY3QsIElPcGVyYXRpb24sIEludmVudG9yeVNlcnZpY2UsIE9wZXJhdGlvblN0YXR1cyB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IFNlcnZpY2VSZWdpc3RyeSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHtcbiAgRGV2aWNlU29mdHdhcmUsXG4gIERldmljZVNvZnR3YXJlQ2hhbmdlLFxuICBJQWR2YW5jZWRTb2Z0d2FyZVNlcnZpY2UsXG4gIFJlcG9zaXRvcnlTZXJ2aWNlLFxuICBSZXBvc2l0b3J5VHlwZVxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL3JlcG9zaXRvcnkvc2hhcmVkJztcbmltcG9ydCB7IGhlYWQgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgQmVoYXZpb3JTdWJqZWN0LCBPYnNlcnZhYmxlLCBvZiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZmlsdGVyLCBtYXAsIHN3aXRjaE1hcCwgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IERldmljZVNvZnR3YXJlU2VydmljZSB9IGZyb20gJy4vZGV2aWNlLXNvZnR3YXJlLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktc29mdHdhcmUtZGV2aWNlLXRhYicsXG4gIHRlbXBsYXRlVXJsOiAnc29mdHdhcmUtZGV2aWNlLXRhYi5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgU29mdHdhcmVEZXZpY2VUYWJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBkZXZpY2VJZDogc3RyaW5nIHwgbnVtYmVyID0gdGhpcy5yb3V0ZS5zbmFwc2hvdC5wYXJlbnQuZGF0YS5jb250ZXh0RGF0YS5pZDtcbiAgZGV2aWNlJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8SU1hbmFnZWRPYmplY3Q+KHRoaXMucm91dGUuc25hcHNob3QucGFyZW50LmRhdGEuY29udGV4dERhdGEpO1xuICB0eXBlc1F1ZXJ5JDogT2JzZXJ2YWJsZTxvYmplY3Q+ID0gdGhpcy5kZXZpY2UkLnBpcGUoXG4gICAgbWFwKGRldmljZSA9PiB7XG4gICAgICBjb25zdCBkZXZpY2VUeXBlUXVlcnkgPSB0aGlzLnJlcG9zaXRvcnkuZ2V0RGV2aWNlVHlwZVF1ZXJ5KFJlcG9zaXRvcnlUeXBlLlNPRlRXQVJFLCBkZXZpY2UpO1xuICAgICAgcmV0dXJuIHRoaXMucmVwb3NpdG9yeS5nZXRTb2Z0d2FyZVR5cGVRdWVyeShkZXZpY2UsIGRldmljZVR5cGVRdWVyeSk7XG4gICAgfSlcbiAgKTtcbiAgbGlzdCQ6IE9ic2VydmFibGU8RGV2aWNlU29mdHdhcmVbXT47XG4gIGNoYW5nZXMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxEZXZpY2VTb2Z0d2FyZUNoYW5nZVtdPihbXSk7XG4gIGNoYW5nZXNPcGVyYXRpb24kID0gbmV3IEJlaGF2aW9yU3ViamVjdDxJT3BlcmF0aW9uPihudWxsKTtcbiAgY2hhbmdlc0luUHJvZ3Jlc3MkOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy5jaGFuZ2VzT3BlcmF0aW9uJC5waXBlKFxuICAgIG1hcChvcGVyYXRpb24gPT4gdGhpcy5pc0luUHJvZ3Jlc3Mob3BlcmF0aW9uKSlcbiAgKTtcbiAgcmVsb2FkaW5nID0gZmFsc2U7XG4gIHNob3dTb2Z0d2FyZUNoYW5nZXMgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIHJlcG9zaXRvcnk6IFJlcG9zaXRvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgaW52ZW50b3J5OiBJbnZlbnRvcnlTZXJ2aWNlLFxuICAgIHByaXZhdGUgZGV2aWNlU29mdHdhcmVTZXJ2aWNlOiBEZXZpY2VTb2Z0d2FyZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzZXJ2aWNlUmVnaXN0cnk6IFNlcnZpY2VSZWdpc3RyeVxuICApIHt9XG5cbiAgYXN5bmMgbmdPbkluaXQoKSB7XG4gICAgY29uc3QgYWR2YW5jZWRTb2Z0d2FyZVNlcnZpY2U6IElBZHZhbmNlZFNvZnR3YXJlU2VydmljZSB8IHVuZGVmaW5lZCA9IGhlYWQoXG4gICAgICB0aGlzLnNlcnZpY2VSZWdpc3RyeS5nZXQoJ2FzbScpXG4gICAgKTtcbiAgICB0aGlzLmxpc3QkID0gdGhpcy5kZXZpY2UkLnBpcGUoXG4gICAgICBzd2l0Y2hNYXAoZGV2aWNlID0+XG4gICAgICAgIGFkdmFuY2VkU29mdHdhcmVTZXJ2aWNlXG4gICAgICAgICAgPyBhZHZhbmNlZFNvZnR3YXJlU2VydmljZVxuICAgICAgICAgICAgICAuaXNBU01BdmFpbGFibGUoKVxuICAgICAgICAgICAgICAudGhlbihpc0FTTUF2YWlsYWJsZSA9PiAoeyBpc0FTTUF2YWlsYWJsZSwgZGV2aWNlIH0pKVxuICAgICAgICAgIDogb2YoeyBpc0FTTUF2YWlsYWJsZTogZmFsc2UsIGRldmljZSB9KVxuICAgICAgKSxcbiAgICAgIG1hcCgoeyBpc0FTTUF2YWlsYWJsZSwgZGV2aWNlIH0pID0+XG4gICAgICAgIC8vIHdpdGggQVNNIGF2YWlsYWJsZSBzb2Z0d2FyZSBpdGVtcyB3aWxsIGJlIHJldHJpZXZlZCBkaXJlY3RseSBpbiB0aGVcbiAgICAgICAgLy8gZGV2aWNlLXNvZnR3YXJlLWxpc3QgY29tcG9uZW50XG4gICAgICAgIGlzQVNNQXZhaWxhYmxlID8gdW5kZWZpbmVkIDogdGhpcy5yZXBvc2l0b3J5LmdldERldmljZVNvZnR3YXJlTGlzdChkZXZpY2UpXG4gICAgICApXG4gICAgKTtcbiAgICBhd2FpdCB0aGlzLmxvYWREZXZpY2UoKTtcbiAgICBhd2FpdCB0aGlzLmxvYWRPcGVyYXRpb24oKTtcbiAgfVxuXG4gIGFkZENoYW5nZXMocmVxdWVzdGVkQ2hhbmdlczogRGV2aWNlU29mdHdhcmVDaGFuZ2VbXSkge1xuICAgIGxldCBzdGFnZWRDaGFuZ2VzID0gWy4uLnRoaXMuY2hhbmdlcyQudmFsdWVdO1xuICAgIHJlcXVlc3RlZENoYW5nZXMuZm9yRWFjaChyZXF1ZXN0ZWRDaGFuZ2UgPT4ge1xuICAgICAgY29uc3QgYWxyZWFkeVN0YWdlZCA9IHN0YWdlZENoYW5nZXMuc29tZShzdGFnZWRDaGFuZ2UgPT5cbiAgICAgICAgdGhpcy5hcmVTYW1lQ2hhbmdlcyhzdGFnZWRDaGFuZ2UsIHJlcXVlc3RlZENoYW5nZSlcbiAgICAgICk7XG4gICAgICBpZiAoIWFscmVhZHlTdGFnZWQpIHtcbiAgICAgICAgc3RhZ2VkQ2hhbmdlcyA9IFsuLi5zdGFnZWRDaGFuZ2VzLCByZXF1ZXN0ZWRDaGFuZ2VdO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMuY2hhbmdlcyQubmV4dChzdGFnZWRDaGFuZ2VzKTtcbiAgfVxuXG4gIGRyb3BDaGFuZ2UoY2hhbmdlVG9CZURyb3BwZWQ6IERldmljZVNvZnR3YXJlQ2hhbmdlKSB7XG4gICAgbGV0IHN0YWdlZENoYW5nZXMgPSBbLi4udGhpcy5jaGFuZ2VzJC52YWx1ZV07XG4gICAgc3RhZ2VkQ2hhbmdlcyA9IHN0YWdlZENoYW5nZXMuZmlsdGVyKFxuICAgICAgc3RhZ2VkQ2hhbmdlID0+ICF0aGlzLmFyZVNhbWVDaGFuZ2VzKHN0YWdlZENoYW5nZSwgY2hhbmdlVG9CZURyb3BwZWQpXG4gICAgKTtcbiAgICB0aGlzLmNoYW5nZXMkLm5leHQoc3RhZ2VkQ2hhbmdlcyk7XG4gIH1cblxuICBhcmVTYW1lQ2hhbmdlcyhjaGFuZ2UxOiBEZXZpY2VTb2Z0d2FyZUNoYW5nZSwgY2hhbmdlMjogRGV2aWNlU29mdHdhcmVDaGFuZ2UpIHtcbiAgICByZXR1cm4gKFxuICAgICAgY2hhbmdlMS5uYW1lID09PSBjaGFuZ2UyLm5hbWUgJiZcbiAgICAgIGNoYW5nZTEudmVyc2lvbiA9PT0gY2hhbmdlMi52ZXJzaW9uICYmXG4gICAgICBjaGFuZ2UxLmFjdGlvbiA9PT0gY2hhbmdlMi5hY3Rpb25cbiAgICApO1xuICB9XG5cbiAgY2xlYXJDaGFuZ2VzKCkge1xuICAgIHRoaXMuY2hhbmdlcyQubmV4dChbXSk7XG4gIH1cblxuICBhc3luYyBsb2FkRGV2aWNlKCkge1xuICAgIHRoaXMucmVsb2FkaW5nID0gdHJ1ZTtcbiAgICB0aGlzLmRldmljZVNvZnR3YXJlU2VydmljZS5yZWxvYWQoKTtcbiAgICBjb25zdCBkZXZpY2UgPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICB0aGlzLmRldmljZVNvZnR3YXJlU2VydmljZS5sb2FkaW5nJFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaWx0ZXIobG9hZGluZyA9PiAhbG9hZGluZyksXG4gICAgICAgICAgdGFrZSgxKVxuICAgICAgICApXG4gICAgICAgIC50b1Byb21pc2UoKSxcbiAgICAgIHRoaXMuaW52ZW50b3J5LmRldGFpbCh0aGlzLmRldmljZUlkLCB7IHdpdGhDaGlsZHJlbjogZmFsc2UgfSkudGhlbihyZXN1bHQgPT4gcmVzdWx0LmRhdGEpXG4gICAgXSkudGhlbigoW18sIGRldmljZV0pID0+IGRldmljZSk7XG4gICAgdGhpcy5kZXZpY2UkLm5leHQoZGV2aWNlKTtcbiAgICB0aGlzLnJlbG9hZGluZyA9IGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgYXBwbHlDaGFuZ2VzKCkge1xuICAgIGNvbnN0IG9wZXJhdGlvbiA9IGF3YWl0IHRoaXMucmVwb3NpdG9yeS5jcmVhdGVTb2Z0d2FyZVVwZGF0ZU9wZXJhdGlvbihcbiAgICAgIHRoaXMuZGV2aWNlJC52YWx1ZSxcbiAgICAgIHRoaXMuY2hhbmdlcyQudmFsdWVcbiAgICApO1xuICAgIGF3YWl0IHRoaXMudHJhY2tPcGVyYXRpb24ob3BlcmF0aW9uKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZE9wZXJhdGlvbigpIHtcbiAgICBjb25zdCBvcGVyYXRpb24gPSBhd2FpdCB0aGlzLnJlcG9zaXRvcnkuZ2V0TGFzdFNvZnR3YXJlVXBkYXRlT3BlcmF0aW9uKHRoaXMuZGV2aWNlSWQpO1xuICAgIGF3YWl0IHRoaXMudHJhY2tPcGVyYXRpb24ob3BlcmF0aW9uKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdHJhY2tPcGVyYXRpb24ob3BlcmF0aW9uOiBJT3BlcmF0aW9uKSB7XG4gICAgaWYgKFtPcGVyYXRpb25TdGF0dXMuU1VDQ0VTU0ZVTCwgT3BlcmF0aW9uU3RhdHVzLkZBSUxFRF0uaW5jbHVkZXMob3BlcmF0aW9uPy5zdGF0dXMpKSB7XG4gICAgICB0aGlzLmNoYW5nZXNPcGVyYXRpb24kLm5leHQodW5kZWZpbmVkKTtcbiAgICB9IGVsc2UgdGhpcy5jaGFuZ2VzT3BlcmF0aW9uJC5uZXh0KG9wZXJhdGlvbik7XG5cbiAgICBpZiAodGhpcy5pc0luUHJvZ3Jlc3Mob3BlcmF0aW9uKSkge1xuICAgICAgYXdhaXQgdGhpcy5kaXNwbGF5Q2hhbmdlc0Zyb21PcGVyYXRpb24ob3BlcmF0aW9uKTtcbiAgICAgIHRoaXMucmVwb3NpdG9yeS5vYnNlcnZlT3BlcmF0aW9uKG9wZXJhdGlvbikuc3Vic2NyaWJlKFxuICAgICAgICBvcGVyYXRpb25VcGRhdGUgPT4ge1xuICAgICAgICAgIHRoaXMuY2hhbmdlc09wZXJhdGlvbiQubmV4dChvcGVyYXRpb25VcGRhdGUpO1xuICAgICAgICAgIGlmIChvcGVyYXRpb25VcGRhdGUuc3RhdHVzID09PSBPcGVyYXRpb25TdGF0dXMuU1VDQ0VTU0ZVTCkge1xuICAgICAgICAgICAgdGhpcy5jbGVhckNoYW5nZXMoKTtcbiAgICAgICAgICAgIHRoaXMubG9hZERldmljZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgb3BlcmF0aW9uVXBkYXRlID0+IHtcbiAgICAgICAgICB0aGlzLmNoYW5nZXNPcGVyYXRpb24kLm5leHQob3BlcmF0aW9uVXBkYXRlKTtcbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRpc3BsYXlDaGFuZ2VzRnJvbU9wZXJhdGlvbihvcGVyYXRpb246IElPcGVyYXRpb24pIHtcbiAgICBjb25zdCBjaGFuZ2VzID0gYXdhaXQgdGhpcy5yZXBvc2l0b3J5LmdldERldmljZVNvZnR3YXJlQ2hhbmdlc0Zyb21PcGVyYXRpb24oXG4gICAgICBvcGVyYXRpb24sXG4gICAgICB0aGlzLmRldmljZSQudmFsdWVcbiAgICApO1xuICAgIHRoaXMuY2hhbmdlcyQubmV4dChjaGFuZ2VzKTtcbiAgfVxuXG4gIHByaXZhdGUgaXNJblByb2dyZXNzKG9wZXJhdGlvbjogSU9wZXJhdGlvbikge1xuICAgIHJldHVybiAoXG4gICAgICBvcGVyYXRpb24gJiYgW09wZXJhdGlvblN0YXR1cy5QRU5ESU5HLCBPcGVyYXRpb25TdGF0dXMuRVhFQ1VUSU5HXS5pbmNsdWRlcyhvcGVyYXRpb24uc3RhdHVzKVxuICAgICk7XG4gIH1cbn1cbiIsIjxjOHktYWN0aW9uLWJhci1pdGVtIFtwbGFjZW1lbnRdPVwiJ3JpZ2h0J1wiPlxuICA8YnV0dG9uXG4gICAgY2xhc3M9XCJidG4gYnRuLWxpbmtcIlxuICAgIHRpdGxlPVwie3sgJ1JlbG9hZCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgIChjbGljayk9XCJsb2FkRGV2aWNlKClcIlxuICA+XG4gICAgPGlcbiAgICAgIGM4eUljb249XCJyZWZyZXNoXCJcbiAgICAgIFtuZ0NsYXNzXT1cInsgJ2ljb24tc3Bpbic6IHJlbG9hZGluZyB9XCJcbiAgICA+PC9pPlxuICAgIHt7ICdSZWxvYWQnIHwgdHJhbnNsYXRlIH19XG4gIDwvYnV0dG9uPlxuPC9jOHktYWN0aW9uLWJhci1pdGVtPlxuXG48ZGl2IGNsYXNzPVwiY2FyZCBzcGxpdC12aWV3LS03LTUgbS1iLTBcIj5cbiAgPGM4eS1pbnN0YWxsZWQtc29mdHdhcmVcbiAgICBjbGFzcz1cInNwbGl0LXZpZXdfX2xpc3RcIlxuICAgIFtkZXZpY2VdPVwiZGV2aWNlJCB8IGFzeW5jXCJcbiAgICBbdHlwZXNRdWVyeV09XCJ0eXBlc1F1ZXJ5JCB8IGFzeW5jXCJcbiAgICBbc29mdHdhcmVMaXN0XT1cImxpc3QkIHwgYXN5bmNcIlxuICAgIFtkZXZpY2VTb2Z0d2FyZUNoYW5nZXNdPVwiY2hhbmdlcyQgfCBhc3luY1wiXG4gICAgW2RldmljZVNvZnR3YXJlQ2hhbmdlc0luUHJvZ3Jlc3NdPVwiY2hhbmdlc0luUHJvZ3Jlc3MkIHwgYXN5bmNcIlxuICAgIChjaGFuZ2VzKT1cImFkZENoYW5nZXMoJGV2ZW50KVwiXG4gICAgKHNob3dTb2Z0d2FyZUNoYW5nZXMpPVwic2hvd1NvZnR3YXJlQ2hhbmdlcyA9IHRydWVcIlxuICA+PC9jOHktaW5zdGFsbGVkLXNvZnR3YXJlPlxuICA8Yzh5LWRldmljZS1zb2Z0d2FyZS1jaGFuZ2VzXG4gICAgY2xhc3M9XCJiZy1sZXZlbC0xIHNwbGl0LXZpZXdfX2RldGFpbFwiXG4gICAgW25nQ2xhc3NdPVwieyAnc3BsaXQtdmlld19fZGV0YWlsLS1zZWxlY3RlZCc6IHNob3dTb2Z0d2FyZUNoYW5nZXMgfVwiXG4gICAgW2RldmljZVNvZnR3YXJlQ2hhbmdlc09wZXJhdGlvbl09XCJjaGFuZ2VzT3BlcmF0aW9uJCB8IGFzeW5jXCJcbiAgICBbY2hhbmdlc109XCJjaGFuZ2VzJCB8IGFzeW5jXCJcbiAgICBbY2hhbmdlc0luUHJvZ3Jlc3NdPVwiY2hhbmdlc0luUHJvZ3Jlc3MkIHwgYXN5bmNcIlxuICAgIChjbGVhcik9XCJjbGVhckNoYW5nZXMoKVwiXG4gICAgKGRyb3ApPVwiZHJvcENoYW5nZSgkZXZlbnQpXCJcbiAgICAoYXBwbHkpPVwiYXBwbHlDaGFuZ2VzKClcIlxuICAgIChoaWRlU29mdHdhcmVDaGFuZ2VzKT1cInNob3dTb2Z0d2FyZUNoYW5nZXMgPSBmYWxzZVwiXG4gID48L2M4eS1kZXZpY2Utc29mdHdhcmUtY2hhbmdlcz5cbjwvZGl2PlxuIl19