UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

240 lines 47.4 kB
import { Component } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { GainsightService, gettext } from '@c8y/ngx-components'; import { cloneDeep, uniq } from 'lodash-es'; import { BsModalRef } from 'ngx-bootstrap/modal'; import { BehaviorSubject, defer, forkJoin, from, of, Subject, throwError } from 'rxjs'; import { catchError, map, mergeMap, shareReplay, switchMap, takeUntil } from 'rxjs/operators'; import { PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION } from './actility-device-registration.model'; import { ActilityDeviceRegistrationService, ActilityErrorName } from './actility-device-registration.service'; import * as i0 from "@angular/core"; import * as i1 from "ngx-bootstrap/modal"; import * as i2 from "./actility-device-registration.service"; import * as i3 from "@c8y/ngx-components"; import * as i4 from "@angular/common"; import * as i5 from "@angular/cdk/stepper"; import * as i6 from "@ngx-formly/core"; export class ActilityDeviceRegistrationComponent { constructor(bsModalRef, registrationService, gainsightService) { this.bsModalRef = bsModalRef; this.registrationService = registrationService; this.gainsightService = gainsightService; this.registrationStepLabels = { next: gettext('Register') }; this.finalStepLabels = { custom: gettext('Close') }; this.state = 'loadPending'; this.errors$ = new BehaviorSubject([]); this.errorMessages$ = this.errors$.pipe(map(errors => errors.map(error => error.message)), map(messages => uniq(messages))); this.connections$ = this.getConnections$(); this.deviceProtocols$ = this.getDeviceProtocols$(); this.unsubscribe$ = new Subject(); this.load$ = this.connections$.pipe(catchError((error) => of(error)), switchMap(connections => { if (connections instanceof Error && connections.name === ActilityErrorName.NoConnectivitySettingsError) { return of([connections]); } return forkJoin([ of(connections), this.deviceProtocols$.pipe(catchError((error) => of(error))) ]); }), map(results => results.filter(result => result instanceof Error)), switchMap(errors => (errors.length === 0 ? of([]) : throwError(errors)))); this.form = new FormGroup({}); this.model = {}; // Formly schema definition to render actility device registration form this.fields = [ { key: 'connection', type: 'typeahead', templateOptions: { label: gettext('Connection'), required: true, c8yForOptions: this.connections$, displayProperty: 'name', valueProperties: ['name'] } }, { key: 'deviceProfile', type: 'typeahead', templateOptions: { label: gettext('Device profile'), required: true, displayProperty: 'name', placeholder: 'IWM-LR3', valueProperties: ['id', 'name', 'typeMAC'] }, hooks: { onInit: field => { const connectionControl = field.form.get('connection'); connectionControl.valueChanges .pipe(takeUntil(this.unsubscribe$), mergeMap(({ name }) => this.getDeviceProfiles$(name))) .subscribe(profiles => { field.templateOptions.c8yForOptions = of(profiles); field.formControl.setValue(null); }, error => { field.form.get('deviceProfile').setErrors({ deviceProfile: true }); field.validators.deviceProfile.message = error.message; }); } }, validators: { deviceProfile: { expression: (control) => { return control.status === 'VALID'; }, message: () => '' } } }, { key: 'deviceType', type: 'typeahead', templateOptions: { label: gettext('Device protocol'), required: true, c8yForOptions: this.deviceProtocols$, displayProperty: 'name', valueProperties: ['id', 'name'] } }, { key: 'devEUI', type: 'input', templateOptions: { placeholder: '0018A20000000004', label: gettext('Device EUI'), required: true, pattern: '^([a-fA-F0-9]{16})$' }, validation: { messages: { pattern: gettext('Must be a valid 16 digit hexadecimal number.') } } }, { key: 'applicationEUI', type: 'input', templateOptions: { placeholder: '70B3D53260000003', label: gettext('Application EUI'), required: true, pattern: '^([a-fA-F0-9]{16})$' }, validation: { messages: { pattern: gettext('Must be a valid 16 digit hexadecimal number.') } } }, { key: 'applicationKey', type: 'input', templateOptions: { label: gettext('Application key'), placeholder: '258DB54023EA74F0D55085F7351737D0', required: true, pattern: '^([a-fA-F0-9]{32})$' }, validation: { messages: { pattern: gettext('Must be a valid 32 digit hexadecimal number.') } } }, { key: 'connectivityPlan', type: 'typeahead', templateOptions: { label: gettext('Connectivity plan'), description: gettext('Only connectivity plans with free slots are displayed'), required: true, placeholder: 'Dev-ope testing CP', displayProperty: 'name', valueProperties: ['id', 'ref', 'name', 'grantedConnections', 'usedConnections'] }, hooks: { onInit: field => { const connectionControl = field.form.get('connection'); connectionControl.valueChanges .pipe(takeUntil(this.unsubscribe$), mergeMap(({ name }) => this.getConnectivityPlans$(name))) .subscribe(profiles => { field.templateOptions.c8yForOptions = of(profiles); field.formControl.setValue(null); }, error => { field.form.get('connectivityPlan').setErrors({ connectivityPlan: true }); field.validators.connectivityPlan.message = error.message; }); } }, validators: { connectivityPlan: { expression: (control) => { return control.status === 'VALID'; }, message: () => '' } } } ]; this.load$.subscribe(() => { this.state = 'loadSuccess'; }, errors => { this.state = 'loadError'; this.errors$.next(errors); }); } getConnectivityPlans$(name) { return defer(() => from(this.registrationService.getConnectivityPlans(name))).pipe(shareReplay(1)); } getDeviceProfiles$(name) { return defer(() => from(this.registrationService.getDeviceProfiles(name))).pipe(shareReplay(1)); } getDeviceProtocols$() { return defer(() => from(this.registrationService.getDeviceProtocols())).pipe(shareReplay(1)); } getConnections$() { return defer(() => from(this.registrationService.getConnections())).pipe(shareReplay(1)); } async register(event) { event.stepper.next(); this.state = 'registrationPending'; try { const actilityDevice = this.getActilityDeviceToSend(); await this.registrationService.register(actilityDevice); this.state = 'registrationSuccess'; this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION.EVENT, { result: PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION.RESULT.SUCCESS, component: PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION.COMPONENT }); } catch (error) { this.state = 'registrationError'; this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION.EVENT, { result: PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION.RESULT.FAILURE, component: PRODUCT_EXPERIENCE_ACTILITY_REGISTRATION.COMPONENT }); this.errors$.next([error]); } } getActilityDeviceToSend() { const actilityDevice = cloneDeep(this.model); actilityDevice.lnsConnectionName = this.model.connection.name; delete actilityDevice.connection; return actilityDevice; } ngOnDestroy() { this.unsubscribe$.next(); this.unsubscribe$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ActilityDeviceRegistrationComponent, deps: [{ token: i1.BsModalRef }, { token: i2.ActilityDeviceRegistrationService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ActilityDeviceRegistrationComponent, selector: "c8y-actility-registration", ngImport: i0, template: "<c8y-modal\n [title]=\"'Actility LoRa registration' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [customFooter]=\"true\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'c8y-device-connect'\"></span>\n </ng-container>\n\n <ng-container *ngIf=\"state === 'loadPending'; else registrationForm\">\n <div class=\"p-16 text-center\">\n <c8y-loading></c8y-loading>\n </div>\n </ng-container>\n\n <!--Formly schema is rendered-->\n <ng-template #registrationForm>\n <c8y-stepper\n [hideStepProgress]=\"true\"\n c8y-modal-body\n linear\n *ngIf=\"(errorMessages$ | async).length === 0; else errorMessagesPresent\"\n >\n <cdk-step [stepControl]=\"form\">\n <div class=\"p-b-16\">\n <p class=\"modal-subtitle sticky-top\">\n {{ 'Register a single Actility device' | translate }}\n </p>\n <formly-form\n class=\"formly-group-array-cols d-block p-l-24 p-r-24 p-t-16\"\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n ></formly-form>\n </div>\n\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n [labels]=\"registrationStepLabels\"\n (onNext)=\"register($event)\"\n (onCancel)=\"bsModalRef.hide()\"\n [showButtons]=\"{ cancel: true, next: true }\"\n [pending]=\"state === 'registrationPending'\"\n [disabled]=\"!form?.valid\"\n ></c8y-stepper-buttons>\n </cdk-step>\n <cdk-step state=\"final\">\n <!--success scenario-->\n <div\n class=\"p-16 text-center\"\n *ngIf=\"state === 'registrationPending'\"\n >\n <c8y-loading></c8y-loading>\n </div>\n <div class=\"m-24\">\n <c8y-operation-result\n class=\"lead m-b-0\"\n type=\"success\"\n *ngIf=\"state === 'registrationSuccess'\"\n text=\"{{ 'Device registered' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n ></c8y-operation-result>\n </div>\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n (onCustom)=\"bsModalRef.hide()\"\n [showButtons]=\"{ custom: true }\"\n [labels]=\"finalStepLabels\"\n ></c8y-stepper-buttons>\n </cdk-step>\n </c8y-stepper>\n </ng-template>\n\n <!--Failure scenario-->\n <ng-template #errorMessagesPresent>\n <div class=\"m-24\">\n <c8y-operation-result\n class=\"lead\"\n type=\"error\"\n *ngIf=\"state === 'registrationError'\"\n text=\"{{ 'Failed to register' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n ></c8y-operation-result>\n <div\n class=\"m-b-8\"\n *ngFor=\"let msg of errorMessages$ | async\"\n data-cy=\"actility-device-registration.component--registration-error\"\n [ngClass]=\"{\n 'text-center': state === 'registrationError',\n 'alert alert-danger': state === 'loadError'\n }\"\n >\n <span [innerHTML]=\"msg | translate\"></span>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Close' | translate }}\"\n type=\"button\"\n (click)=\"bsModalRef.hide()\"\n >\n {{ 'Close' | translate }}\n </button>\n </div>\n </ng-template>\n</c8y-modal>\n", dependencies: [{ kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "component", type: i3.OperationResultComponent, selector: "c8y-operation-result", inputs: ["text", "vertical", "size", "type"] }, { kind: "component", type: i3.ModalComponent, selector: "c8y-modal", inputs: ["disabled", "close", "dismiss", "title", "body", "customFooter", "headerClasses", "labels"], outputs: ["onDismiss", "onClose"] }, { kind: "component", type: i3.C8yStepper, selector: "c8y-stepper", inputs: ["disableDefaultIcons", "disableProgressButtons", "customClasses", "hideStepProgress", "useStepLabelsAsTitlesOnly"], outputs: ["onStepChange"] }, { kind: "component", type: i5.CdkStep, selector: "cdk-step", inputs: ["stepControl", "label", "errorMessage", "aria-label", "aria-labelledby", "state", "editable", "optional", "completed", "hasError"], outputs: ["interacted"], exportAs: ["cdkStep"] }, { kind: "component", type: i3.C8yStepperButtons, selector: "c8y-stepper-buttons", inputs: ["labels", "pending", "disabled", "showButtons"], outputs: ["onCancel", "onNext", "onBack", "onCustom"] }, { kind: "component", type: i6.FormlyForm, selector: "formly-form", inputs: ["form", "model", "fields", "options"], outputs: ["modelChange"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ActilityDeviceRegistrationComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-actility-registration', template: "<c8y-modal\n [title]=\"'Actility LoRa registration' | translate\"\n [headerClasses]=\"'dialog-header'\"\n [customFooter]=\"true\"\n>\n <ng-container c8y-modal-title>\n <span [c8yIcon]=\"'c8y-device-connect'\"></span>\n </ng-container>\n\n <ng-container *ngIf=\"state === 'loadPending'; else registrationForm\">\n <div class=\"p-16 text-center\">\n <c8y-loading></c8y-loading>\n </div>\n </ng-container>\n\n <!--Formly schema is rendered-->\n <ng-template #registrationForm>\n <c8y-stepper\n [hideStepProgress]=\"true\"\n c8y-modal-body\n linear\n *ngIf=\"(errorMessages$ | async).length === 0; else errorMessagesPresent\"\n >\n <cdk-step [stepControl]=\"form\">\n <div class=\"p-b-16\">\n <p class=\"modal-subtitle sticky-top\">\n {{ 'Register a single Actility device' | translate }}\n </p>\n <formly-form\n class=\"formly-group-array-cols d-block p-l-24 p-r-24 p-t-16\"\n [form]=\"form\"\n [fields]=\"fields\"\n [model]=\"model\"\n ></formly-form>\n </div>\n\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n [labels]=\"registrationStepLabels\"\n (onNext)=\"register($event)\"\n (onCancel)=\"bsModalRef.hide()\"\n [showButtons]=\"{ cancel: true, next: true }\"\n [pending]=\"state === 'registrationPending'\"\n [disabled]=\"!form?.valid\"\n ></c8y-stepper-buttons>\n </cdk-step>\n <cdk-step state=\"final\">\n <!--success scenario-->\n <div\n class=\"p-16 text-center\"\n *ngIf=\"state === 'registrationPending'\"\n >\n <c8y-loading></c8y-loading>\n </div>\n <div class=\"m-24\">\n <c8y-operation-result\n class=\"lead m-b-0\"\n type=\"success\"\n *ngIf=\"state === 'registrationSuccess'\"\n text=\"{{ 'Device registered' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n ></c8y-operation-result>\n </div>\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-level-0\"\n (onCustom)=\"bsModalRef.hide()\"\n [showButtons]=\"{ custom: true }\"\n [labels]=\"finalStepLabels\"\n ></c8y-stepper-buttons>\n </cdk-step>\n </c8y-stepper>\n </ng-template>\n\n <!--Failure scenario-->\n <ng-template #errorMessagesPresent>\n <div class=\"m-24\">\n <c8y-operation-result\n class=\"lead\"\n type=\"error\"\n *ngIf=\"state === 'registrationError'\"\n text=\"{{ 'Failed to register' | translate }}\"\n [size]=\"84\"\n [vertical]=\"true\"\n ></c8y-operation-result>\n <div\n class=\"m-b-8\"\n *ngFor=\"let msg of errorMessages$ | async\"\n data-cy=\"actility-device-registration.component--registration-error\"\n [ngClass]=\"{\n 'text-center': state === 'registrationError',\n 'alert alert-danger': state === 'loadError'\n }\"\n >\n <span [innerHTML]=\"msg | translate\"></span>\n </div>\n </div>\n <div class=\"modal-footer\">\n <button\n class=\"btn btn-default\"\n title=\"{{ 'Close' | translate }}\"\n type=\"button\"\n (click)=\"bsModalRef.hide()\"\n >\n {{ 'Close' | translate }}\n </button>\n </div>\n </ng-template>\n</c8y-modal>\n" }] }], ctorParameters: () => [{ type: i1.BsModalRef }, { type: i2.ActilityDeviceRegistrationService }, { type: i3.GainsightService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aWxpdHktZGV2aWNlLXJlZ2lzdHJhdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9hY3RpbGl0eS1kZXZpY2UtcmVnaXN0cmF0aW9uL2FjdGlsaXR5LWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vYWN0aWxpdHktZGV2aWNlLXJlZ2lzdHJhdGlvbi9hY3RpbGl0eS1kZXZpY2UtcmVnaXN0cmF0aW9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUMsT0FBTyxFQUFtQixTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1RCxPQUFPLEVBQWMsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFNUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDNUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2pELE9BQU8sRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdkYsT0FBTyxFQUFFLFVBQVUsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUYsT0FBTyxFQUVMLHdDQUF3QyxFQUN6QyxNQUFNLHNDQUFzQyxDQUFDO0FBQzlDLE9BQU8sRUFDTCxpQ0FBaUMsRUFDakMsaUJBQWlCLEVBQ2xCLE1BQU0sd0NBQXdDLENBQUM7Ozs7Ozs7O0FBWWhELE1BQU0sT0FBTyxtQ0FBbUM7SUErTDlDLFlBQ1MsVUFBc0IsRUFDckIsbUJBQXNELEVBQ3RELGdCQUFrQztRQUZuQyxlQUFVLEdB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Q0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsd0NBQXdDLENBQUMsS0FBSyxFQUFFO2dCQUNqRixNQUFNLEVBQUUsd0NBQXdDLENBQUMsTUFBTSxDQUFDLE9BQU87Z0JBQy9ELFNBQVMsRUFBRSx3Q0FBd0MsQ0FBQyxTQUFTO2FBQzlELENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztRQUM3QixDQUFDO0lBQ0gsQ0FBQztJQUVELHVCQUF1QjtRQUNyQixNQUFNLGNBQWMsR0FBK0IsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6RSxjQUFjLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDO1FBQzlELE9BQVEsY0FBc0IsQ0FBQyxVQUFVLENBQUM7UUFDMUMsT0FBTyxjQUFjLENBQUM7SUFDeEIsQ0FBQztJQUNELFdBQVc7UUFDVCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDL0IsQ0FBQzsrR0EvUFUsbUNBQW1DO21HQUFuQyxtQ0FBbUMsaUVDNUJoRCw2K0dBNkdBOzs0RkRqRmEsbUNBQW1DO2tCQUovQyxTQUFTOytCQUNFLDJCQUEyQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENka1N0ZXAgfSBmcm9tICdAYW5ndWxhci9jZGsvc3RlcHBlcic7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQzh5U3RlcHBlciwgR2FpbnNpZ2h0U2VydmljZSwgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgRm9ybWx5RmllbGRDb25maWcgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlJztcbmltcG9ydCB7IGNsb25lRGVlcCwgdW5pcSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBCc01vZGFsUmVmIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGRlZmVyLCBmb3JrSm9pbiwgZnJvbSwgb2YsIFN1YmplY3QsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgbWVyZ2VNYXAsIHNoYXJlUmVwbGF5LCBzd2l0Y2hNYXAsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIEFjdGlsaXR5RGV2aWNlUmVnaXN0cmF0aW9uLFxuICBQUk9EVUNUX0VYUEVSSUVOQ0VfQUNUSUxJVFlfUkVHSVNUUkFUSU9OXG59IGZyb20gJy4vYWN0aWxpdHktZGV2aWNlLXJlZ2lzdHJhdGlvbi5tb2RlbCc7XG5pbXBvcnQge1xuICBBY3RpbGl0eURldmljZVJlZ2lzdHJhdGlvblNlcnZpY2UsXG4gIEFjdGlsaXR5RXJyb3JOYW1lXG59IGZyb20gJy4vYWN0aWxpdHktZGV2aWNlLXJlZ2lzdHJhdGlvbi5zZXJ2aWNlJztcbnR5cGUgQWN0aWxpdHlTdGF0ZSA9XG4gIHwgJ2xvYWRQZW5kaW5nJ1xuICB8ICdsb2FkU3VjY2VzcydcbiAgfCAnbG9hZEVycm9yJ1xuICB8ICdyZWdpc3RyYXRpb25QZW5kaW5nJ1xuICB8ICdyZWdpc3RyYXRpb25TdWNjZXNzJ1xuICB8ICdyZWdpc3RyYXRpb25FcnJvcic7XG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktYWN0aWxpdHktcmVnaXN0cmF0aW9uJyxcbiAgdGVtcGxhdGVVcmw6ICdhY3RpbGl0eS1kZXZpY2UtcmVnaXN0cmF0aW9uLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBBY3RpbGl0eURldmljZVJlZ2lzdHJhdGlvbkNvbXBvbmVudCB7XG4gIHN0ZXBwZXI6IEM4eVN0ZXBwZXI7XG4gIHJlZ2lzdHJhdGlvblN0ZXBMYWJlbHMgPSB7XG4gICAgbmV4dDogZ2V0dGV4dCgnUmVnaXN0ZXInKVxuICB9O1xuICBmaW5hbFN0ZXBMYWJlbHMgPSB7XG4gICAgY3VzdG9tOiBnZXR0ZXh0KCdDbG9zZScpXG4gIH07XG5cbiAgc3RhdGU6IEFjdGlsaXR5U3RhdGUgPSAnbG9hZFBlbmRpbmcnO1xuICBlcnJvcnMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxFcnJvcltdPihbXSk7XG4gIGVycm9yTWVzc2FnZXMkID0gdGhpcy5lcnJvcnMkLnBpcGUoXG4gICAgbWFwKGVycm9ycyA9PiBlcnJvcnMubWFwKGVycm9yID0+IGVycm9yLm1lc3NhZ2UpKSxcbiAgICBtYXAobWVzc2FnZXMgPT4gdW5pcShtZXNzYWdlcykpXG4gICk7XG5cbiAgY29ubmVjdGlvbnMkID0gdGhpcy5nZXRDb25uZWN0aW9ucyQoKTtcbiAgZGV2aWNlUHJvdG9jb2xzJCA9IHRoaXMuZ2V0RGV2aWNlUHJvdG9jb2xzJCgpO1xuICB1bnN1YnNjcmliZSQ6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuICBsb2FkJCA9IHRoaXMuY29ubmVjdGlvbnMkLnBpcGUoXG4gICAgY2F0Y2hFcnJvcigoZXJyb3I6IEVycm9yKSA9PiBvZihlcnJvcikpLFxuICAgIHN3aXRjaE1hcChjb25uZWN0aW9ucyA9PiB7XG4gICAgICBpZiAoXG4gICAgICAgIGNvbm5lY3Rpb25zIGluc3RhbmNlb2YgRXJyb3IgJiZcbiAgICAgICAgY29ubmVjdGlvbnMubmFtZSA9PT0gQWN0aWxpdHlFcnJvck5hbWUuTm9Db25uZWN0aXZpdHlTZXR0aW5nc0Vycm9yXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIG9mKFtjb25uZWN0aW9uc10pO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gZm9ya0pvaW4oW1xuICAgICAgICBvZihjb25uZWN0aW9ucyksXG4gICAgICAgIHRoaXMuZGV2aWNlUHJvdG9jb2xzJC5waXBlKGNhdGNoRXJyb3IoKGVycm9yOiBFcnJvcikgPT4gb2YoZXJyb3IpKSlcbiAgICAgIF0pO1xuICAgIH0pLFxuICAgIG1hcChyZXN1bHRzID0+IHJlc3VsdHMuZmlsdGVyKHJlc3VsdCA9PiByZXN1bHQgaW5zdGFuY2VvZiBFcnJvcikpLFxuICAgIHN3aXRjaE1hcChlcnJvcnMgPT4gKGVycm9ycy5sZW5ndGggPT09IDAgPyBvZihbXSkgOiB0aHJvd0Vycm9yKGVycm9ycykpKVxuICApO1xuXG4gIGZvcm0gPSBuZXcgRm9ybUdyb3VwKHt9KTtcbiAgbW9kZWwgPSB7fSBhcyBBY3RpbGl0eURldmljZVJlZ2lzdHJhdGlvbjtcblxuICAvLyBGb3JtbHkgc2NoZW1hIGRlZmluaXRpb24gdG8gcmVuZGVyIGFjdGlsaXR5IGRldmljZSByZWdpc3RyYXRpb24gZm9ybVxuICBmaWVsZHM6IEZvcm1seUZpZWxkQ29uZmlnW10gPSBbXG4gICAge1xuICAgICAga2V5OiAnY29ubmVjdGlvbicsXG4gICAgICB0eXBlOiAndHlwZWFoZWFkJyxcbiAgICAgIHRlbXBsYXRlT3B0aW9uczoge1xuICAgICAgICBsYWJlbDogZ2V0dGV4dCgnQ29ubmVjdGlvbicpLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgYzh5Rm9yT3B0aW9uczogdGhpcy5jb25uZWN0aW9ucyQsXG4gICAgICAgIGRpc3BsYXlQcm9wZXJ0eTogJ25hbWUnLFxuICAgICAgICB2YWx1ZVByb3BlcnRpZXM6IFsnbmFtZSddXG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBrZXk6ICdkZXZpY2VQcm9maWxlJyxcbiAgICAgIHR5cGU6ICd0eXBlYWhlYWQnLFxuICAgICAgdGVtcGxhdGVPcHRpb25zOiB7XG4gICAgICAgIGxhYmVsOiBnZXR0ZXh0KCdEZXZpY2UgcHJvZmlsZScpLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgZGlzcGxheVByb3BlcnR5OiAnbmFtZScsXG4gICAgICAgIHBsYWNlaG9sZGVyOiAnSVdNLUxSMycsXG4gICAgICAgIHZhbHVlUHJvcGVydGllczogWydpZCcsICduYW1lJywgJ3R5cGVNQUMnXVxuICAgICAgfSxcbiAgICAgIGhvb2tzOiB7XG4gICAgICAgIG9uSW5pdDogZmllbGQgPT4ge1xuICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25Db250cm9sID0gZmllbGQuZm9ybS5nZXQoJ2Nvbm5lY3Rpb24nKTtcbiAgICAgICAgICBjb25uZWN0aW9uQ29udHJvbC52YWx1ZUNoYW5nZXNcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSQpLFxuICAgICAgICAgICAgICBtZXJnZU1hcCgoeyBuYW1lIH0pID0+IHRoaXMuZ2V0RGV2aWNlUHJvZmlsZXMkKG5hbWUpKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZShcbiAgICAgICAgICAgICAgcHJvZmlsZXMgPT4ge1xuICAgICAgICAgICAgICAgIGZpZWxkLnRlbXBsYXRlT3B0aW9ucy5jOHlGb3JPcHRpb25zID0gb2YocHJvZmlsZXMpO1xuICAgICAgICAgICAgICAgIGZpZWxkLmZvcm1Db250cm9sLnNldFZhbHVlKG51bGwpO1xuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBlcnJvciA9PiB7XG4gICAgICAgICAgICAgICAgZmllbGQuZm9ybS5nZXQoJ2RldmljZVByb2ZpbGUnKS5zZXRFcnJvcnMoeyBkZXZpY2VQcm9maWxlOiB0cnVlIH0pO1xuICAgICAgICAgICAgICAgIGZpZWxkLnZhbGlkYXRvcnMuZGV2aWNlUHJvZmlsZS5tZXNzYWdlID0gZXJyb3IubWVzc2FnZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIHZhbGlkYXRvcnM6IHtcbiAgICAgICAgZGV2aWNlUHJvZmlsZToge1xuICAgICAgICAgIGV4cHJlc3Npb246IChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjb250cm9sLnN0YXR1cyA9PT0gJ1ZBTElEJztcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1lc3NhZ2U6ICgpID0+ICcnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGtleTogJ2RldmljZVR5cGUnLFxuICAgICAgdHlwZTogJ3R5cGVhaGVhZCcsXG4gICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ0RldmljZSBwcm90b2NvbCcpLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgYzh5Rm9yT3B0aW9uczogdGhpcy5kZXZpY2VQcm90b2NvbHMkLFxuICAgICAgICBkaXNwbGF5UHJvcGVydHk6ICduYW1lJyxcbiAgICAgICAgdmFsdWVQcm9wZXJ0aWVzOiBbJ2lkJywgJ25hbWUnXVxuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAga2V5OiAnZGV2RVVJJyxcbiAgICAgIHR5cGU6ICdpbnB1dCcsXG4gICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgcGxhY2Vob2xkZXI6ICcwMDE4QTIwMDAwMDAwMDA0JyxcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ0RldmljZSBFVUknKSxcbiAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgIHBhdHRlcm46ICdeKFthLWZBLUYwLTldezE2fSkkJ1xuICAgICAgfSxcbiAgICAgIHZhbGlkYXRpb246IHtcbiAgICAgICAgbWVzc2FnZXM6IHtcbiAgICAgICAgICBwYXR0ZXJuOiBnZXR0ZXh0KCdNdXN0IGJlIGEgdmFsaWQgMTYgZGlnaXQgaGV4YWRlY2ltYWwgbnVtYmVyLicpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGtleTogJ2FwcGxpY2F0aW9uRVVJJyxcbiAgICAgIHR5cGU6ICdpbnB1dCcsXG4gICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgcGxhY2Vob2xkZXI6ICc3MEIzRDUzMjYwMDAwMDAzJyxcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ0FwcGxpY2F0aW9uIEVVSScpLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgcGF0dGVybjogJ14oW2EtZkEtRjAtOV17MTZ9KSQnXG4gICAgICB9LFxuICAgICAgdmFsaWRhdGlvbjoge1xuICAgICAgICBtZXNzYWdlczoge1xuICAgICAgICAgIHBhdHRlcm46IGdldHRleHQoJ011c3QgYmUgYSB2YWxpZCAxNiBkaWdpdCBoZXhhZGVjaW1hbCBudW1iZXIuJylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAga2V5OiAnYXBwbGljYXRpb25LZXknLFxuICAgICAgdHlwZTogJ2lucHV0JyxcbiAgICAgIHRlbXBsYXRlT3B0aW9uczoge1xuICAgICAgICBsYWJlbDogZ2V0dGV4dCgnQXBwbGljYXRpb24ga2V5JyksXG4gICAgICAgIHBsYWNlaG9sZGVyOiAnMjU4REI1NDAyM0VBNzRGMEQ1NTA4NUY3MzUxNzM3RDAnLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgcGF0dGVybjogJ14oW2EtZkEtRjAtOV17MzJ9KSQnXG4gICAgICB9LFxuICAgICAgdmFsaWRhdGlvbjoge1xuICAgICAgICBtZXNzYWdlczoge1xuICAgICAgICAgIHBhdHRlcm46IGdldHRleHQoJ011c3QgYmUgYSB2YWxpZCAzMiBkaWdpdCBoZXhhZGVjaW1hbCBudW1iZXIuJylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAga2V5OiAnY29ubmVjdGl2aXR5UGxhbicsXG4gICAgICB0eXBlOiAndHlwZWFoZWFkJyxcbiAgICAgIHRlbXBsYXRlT3B0aW9uczoge1xuICAgICAgICBsYWJlbDogZ2V0dGV4dCgnQ29ubmVjdGl2aXR5IHBsYW4nKSxcbiAgICAgICAgZGVzY3JpcHRpb246IGdldHRleHQoJ09ubHkgY29ubmVjdGl2aXR5IHBsYW5zIHdpdGggZnJlZSBzbG90cyBhcmUgZGlzcGxheWVkJyksXG4gICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICBwbGFjZWhvbGRlcjogJ0Rldi1vcGUgdGVzdGluZyBDUCcsXG4gICAgICAgIGRpc3BsYXlQcm9wZXJ0eTogJ25hbWUnLFxuICAgICAgICB2YWx1ZVByb3BlcnRpZXM6IFsnaWQnLCAncmVmJywgJ25hbWUnLCAnZ3JhbnRlZENvbm5lY3Rpb25zJywgJ3VzZWRDb25uZWN0aW9ucyddXG4gICAgICB9LFxuICAgICAgaG9va3M6IHtcbiAgICAgICAgb25Jbml0OiBmaWVsZCA9PiB7XG4gICAgICAgICAgY29uc3QgY29ubmVjdGlvbkNvbnRyb2wgPSBmaWVsZC5mb3JtLmdldCgnY29ubmVjdGlvbicpO1xuICAgICAgICAgIGNvbm5lY3Rpb25Db250cm9sLnZhbHVlQ2hhbmdlc1xuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLnVuc3Vic2NyaWJlJCksXG4gICAgICAgICAgICAgIG1lcmdlTWFwKCh7IG5hbWUgfSkgPT4gdGhpcy5nZXRDb25uZWN0aXZpdHlQbGFucyQobmFtZSkpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKFxuICAgICAgICAgICAgICBwcm9maWxlcyA9PiB7XG4gICAgICAgICAgICAgICAgZmllbGQudGVtcGxhdGVPcHRpb25zLmM4eUZvck9wdGlvbnMgPSBvZihwcm9maWxlcyk7XG4gICAgICAgICAgICAgICAgZmllbGQuZm9ybUNvbnRyb2wuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBmaWVsZC5mb3JtLmdldCgnY29ubmVjdGl2aXR5UGxhbicpLnNldEVycm9ycyh7IGNvbm5lY3Rpdml0eVBsYW46IHRydWUgfSk7XG4gICAgICAgICAgICAgICAgZmllbGQudmFsaWRhdG9ycy5jb25uZWN0aXZpdHlQbGFuLm1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdmFsaWRhdG9yczoge1xuICAgICAgICBjb25uZWN0aXZpdHlQbGFuOiB7XG4gICAgICAgICAgZXhwcmVzc2lvbjogKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnRyb2wuc3RhdHVzID09PSAnVkFMSUQnO1xuICAgICAgICAgIH0sXG4gICAgICAgICAgbWVzc2FnZTogKCkgPT4gJydcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgYnNNb2RhbFJlZjogQnNNb2RhbFJlZixcbiAgICBwcml2YXRlIHJlZ2lzdHJhdGlvblNlcnZpY2U6IEFjdGlsaXR5RGV2aWNlUmVnaXN0cmF0aW9uU2VydmljZSxcbiAgICBwcml2YXRlIGdhaW5zaWdodFNlcnZpY2U6IEdhaW5zaWdodFNlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5sb2FkJC5zdWJzY3JpYmUoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHRoaXMuc3RhdGUgPSAnbG9hZFN1Y2Nlc3MnO1xuICAgICAgfSxcbiAgICAgIGVycm9ycyA9PiB7XG4gICAgICAgIHRoaXMuc3RhdGUgPSAnbG9hZEVycm9yJztcbiAgICAgICAgdGhpcy5lcnJvcnMkLm5leHQoZXJyb3JzKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgZ2V0Q29ubmVjdGl2aXR5UGxhbnMkKG5hbWUpIHtcbiAgICByZXR1cm4gZGVmZXIoKCkgPT4gZnJvbSh0aGlzLnJlZ2lzdHJhdGlvblNlcnZpY2UuZ2V0Q29ubmVjdGl2aXR5UGxhbnMobmFtZSkpKS5waXBlKFxuICAgICAgc2hhcmVSZXBsYXkoMSlcbiAgICApO1xuICB9XG5cbiAgZ2V0RGV2aWNlUHJvZmlsZXMkKG5hbWUpIHtcbiAgICByZXR1cm4gZGVmZXIoKCkgPT4gZnJvbSh0aGlzLnJlZ2lzdHJhdGlvblNlcnZpY2UuZ2V0RGV2aWNlUHJvZmlsZXMobmFtZSkpKS5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgfVxuXG4gIGdldERldmljZVByb3RvY29scyQoKSB7XG4gICAgcmV0dXJuIGRlZmVyKCgpID0+IGZyb20odGhpcy5yZWdpc3RyYXRpb25TZXJ2aWNlLmdldERldmljZVByb3RvY29scygpKSkucGlwZShzaGFyZVJlcGxheSgxKSk7XG4gIH1cblxuICBnZXRDb25uZWN0aW9ucyQoKSB7XG4gICAgcmV0dXJuIGRlZmVyKCgpID0+IGZyb20odGhpcy5yZWdpc3RyYXRpb25TZXJ2aWNlLmdldENvbm5lY3Rpb25zKCkpKS5waXBlKHNoYXJlUmVwbGF5KDEpKTtcbiAgfVxuXG4gIGFzeW5jIHJlZ2lzdGVyKGV2ZW50OiB7IHN0ZXBwZXI6IEM4eVN0ZXBwZXI7IHN0ZXA6IENka1N0ZXAgfSkge1xuICAgIGV2ZW50LnN0ZXBwZXIubmV4dCgpO1xuICAgIHRoaXMuc3RhdGUgPSAncmVnaXN0cmF0aW9uUGVuZGluZyc7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFjdGlsaXR5RGV2aWNlID0gdGhpcy5nZXRBY3RpbGl0eURldmljZVRvU2VuZCgpO1xuICAgICAgYXdhaXQgdGhpcy5yZWdpc3RyYXRpb25TZXJ2aWNlLnJlZ2lzdGVyKGFjdGlsaXR5RGV2aWNlKTtcbiAgICAgIHRoaXMuc3RhdGUgPSAncmVnaXN0cmF0aW9uU3VjY2Vzcyc7XG4gICAgICB0aGlzLmdhaW5zaWdodFNlcnZpY2UudHJpZ2dlckV2ZW50KFBST0RVQ1RfRVhQRVJJRU5DRV9BQ1RJTElUWV9SRUdJU1RSQVRJT04uRVZFTlQsIHtcbiAgICAgICAgcmVzdWx0OiBQUk9EVUNUX0VYUEVSSUVOQ0VfQUNUSUxJVFlfUkVHSVNUUkFUSU9OLlJFU1VMVC5TVUNDRVNTLFxuICAgICAgICBjb21wb25lbnQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9BQ1RJTElUWV9SRUdJU1RSQVRJT04uQ09NUE9ORU5UXG4gICAgICB9KTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgdGhpcy5zdGF0ZSA9ICdyZWdpc3RyYXRpb25FcnJvcic7XG4gICAgICB0aGlzLmdhaW5zaWdodFNlcnZpY2UudHJpZ2dlckV2ZW50KFBST0RVQ1RfRVhQRVJJRU5DRV9BQ1RJTElUWV9SRUdJU1RSQVRJT04uRVZFTlQsIHtcbiAgICAgICAgcmVzdWx0OiBQUk9EVUNUX0VYUEVSSUVOQ0VfQUNUSUxJVFlfUkVHSVNUUkFUSU9OLlJFU1VMVC5GQUlMVVJFLFxuICAgICAgICBjb21wb25lbnQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9BQ1RJTElUWV9SRUdJU1RSQVRJT04uQ09NUE9ORU5UXG4gICAgICB9KTtcbiAgICAgIHRoaXMuZXJyb3JzJC5uZXh0KFtlcnJvcl0pO1xuICAgIH1cbiAgfVxuXG4gIGdldEFjdGlsaXR5RGV2aWNlVG9TZW5kKCkge1xuICAgIGNvbnN0IGFjdGlsaXR5RGV2aWNlOiBBY3RpbGl0eURldmljZVJlZ2lzdHJhdGlvbiA9IGNsb25lRGVlcCh0aGlzLm1vZGVsKTtcbiAgICBhY3RpbGl0eURldmljZS5sbnNDb25uZWN0aW9uTmFtZSA9IHRoaXMubW9kZWwuY29ubmVjdGlvbi5uYW1lO1xuICAgIGRlbGV0ZSAoYWN0aWxpdHlEZXZpY2UgYXMgYW55KS5jb25uZWN0aW9uO1xuICAgIHJldHVybiBhY3RpbGl0eURldmljZTtcbiAgfVxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVuc3Vic2NyaWJlJC5uZXh0KCk7XG4gICAgdGhpcy51bnN1YnNjcmliZSQuY29tcGxldGUoKTtcbiAgfVxufVxuIiwiPGM4eS1tb2RhbFxuICBbdGl0bGVdPVwiJ0FjdGlsaXR5IExvUmEgcmVnaXN0cmF0aW9uJyB8IHRyYW5zbGF0ZVwiXG4gIFtoZWFkZXJDbGFzc2VzXT1cIidkaWFsb2ctaGVhZGVyJ1wiXG4gIFtjdXN0b21Gb290ZXJdPVwidHJ1ZVwiXG4+XG4gIDxuZy1jb250YWluZXIgYzh5LW1vZGFsLXRpdGxlPlxuICAgIDxzcGFuIFtjOHlJY29uXT1cIidjOHktZGV2aWNlLWNvbm5lY3QnXCI+PC9zcGFuPlxuICA8L25nLWNvbnRhaW5lcj5cblxuICA8bmctY29udGFpbmVyICpuZ0lmPVwic3RhdGUgPT09ICdsb2FkUGVuZGluZyc7IGVsc2UgcmVnaXN0cmF0aW9uRm9ybVwiPlxuICAgIDxkaXYgY2xhc3M9XCJwLTE2IHRleHQtY2VudGVyXCI+XG4gICAgICA8Yzh5LWxvYWRpbmc+PC9jOHktbG9hZGluZz5cbiAgICA8L2Rpdj5cbiAgPC9uZy1jb250YWluZXI+XG5cbiAgPCEtLUZvcm1seSBzY2hlbWEgaXMgcmVuZGVyZWQtLT5cbiAgPG5nLXRlbXBsYXRlICNyZWdpc3RyYXRpb25Gb3JtPlxuICAgIDxjOHktc3RlcHBlclxuICAgICAgW2hpZGVTdGVwUHJvZ3Jlc3NdPVwidHJ1ZVwiXG4gICAgICBjOHktbW9kYWwtYm9keVxuICAgICAgbGluZWFyXG4gICAgICAqbmdJZj1cIihlcnJvck1lc3NhZ2VzJCB8IGFzeW5jKS5sZW5ndGggPT09IDA7IGVsc2UgZXJyb3JNZXNzYWdlc1ByZXNlbnRcIlxuICAgID5cbiAgICAgIDxjZGstc3RlcCBbc3RlcENvbnRyb2xdPVwiZm9ybVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC1iLTE2XCI+XG4gICAgICAgICAgPHAgY2xhc3M9XCJtb2RhbC1zdWJ0aXRsZSBzdGlja3ktdG9wXCI+XG4gICAgICAgICAgICB7eyAnUmVnaXN0ZXIgYSBzaW5nbGUgQWN0aWxpdHkgZGV2aWNlJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvcD5cbiAgICAgICAgICA8Zm9ybWx5LWZvcm1cbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybWx5LWdyb3VwLWFycmF5LWNvbHMgZC1ibG9jayBwLWwtMjQgcC1yLTI0IHAtdC0xNlwiXG4gICAgICAgICAgICBbZm9ybV09XCJmb3JtXCJcbiAgICAgICAgICAgIFtmaWVsZHNdPVwiZmllbGRzXCJcbiAgICAgICAgICAgIFttb2RlbF09XCJtb2RlbFwiXG4gICAgICAgICAgPjwvZm9ybWx5LWZvcm0+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxjOHktc3RlcHBlci1idXR0b25zXG4gICAgICAgICAgY2xhc3M9XCJzdGlja3ktYm90dG9tIGQtYmxvY2sgcC10LTE2IHAtYi0xNiBzZXBhcmF0b3ItdG9wIGJnLWxldmVsLTBcIlxuICAgICAgICAgIFtsYWJlbHNdPVwicmVnaXN0cmF0aW9uU3RlcExhYmVsc1wiXG4gICAgICAgICAgKG9uTmV4dCk9XCJyZWdpc3RlcigkZXZlbnQpXCJcbiAgICAgICAgICAob25DYW5jZWwpPVwiYnNNb2RhbFJlZi5oaWRlKClcIlxuICAgICAgICAgIFtzaG93QnV0dG9uc109XCJ7IGNhbmNlbDogdHJ1ZSwgbmV4dDogdHJ1ZSB9XCJcbiAgICAgICAgICBbcGVuZGluZ109XCJzdGF0ZSA9PT0gJ3JlZ2lzdHJhdGlvblBlbmRpbmcnXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiIWZvcm0/LnZhbGlkXCJcbiAgICAgICAgPjwvYzh5LXN0ZXBwZXItYnV0dG9ucz5cbiAgICAgIDwvY2RrLXN0ZXA+XG4gICAgICA8Y2RrLXN0ZXAgc3RhdGU9XCJmaW5hbFwiPlxuICAgICAgICA8IS0tc3VjY2VzcyBzY2VuYXJpby0tPlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgY2xhc3M9XCJwLTE2IHRleHQtY2VudGVyXCJcbiAgICAgICAgICAqbmdJZj1cInN0YXRlID09PSAncmVnaXN0cmF0aW9uUGVuZGluZydcIlxuICAgICAgICA+XG4gICAgICAgICAgPGM4eS1sb2FkaW5nPjwvYzh5LWxvYWRpbmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibS0yNFwiPlxuICAgICAgICAgIDxjOHktb3BlcmF0aW9uLXJlc3VsdFxuICAgICAgICAgICAgY2xhc3M9XCJsZWFkIG0tYi0wXCJcbiAgICAgICAgICAgIHR5cGU9XCJzdWNjZXNzXCJcbiAgICAgICAgICAgICpuZ0lmPVwic3RhdGUgPT09ICdyZWdpc3RyYXRpb25TdWNjZXNzJ1wiXG4gICAgICAgICAgICB0ZXh0PVwie3sgJ0RldmljZSByZWdpc3RlcmVkJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICBbc2l6ZV09XCI4NFwiXG4gICAgICAgICAgICBbdmVydGljYWxdPVwidHJ1ZVwiXG4gICAgICAgICAgPjwvYzh5LW9wZXJhdGlvbi1yZXN1bHQ+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8Yzh5LXN0ZXBwZXItYnV0dG9uc1xuICAgICAgICAgIGNsYXNzPVwic3RpY2t5LWJvdHRvbSBkLWJsb2NrIHAtdC0xNiBwLWItMTYgc2VwYXJhdG9yLXRvcCBiZy1sZXZlbC0wXCJcbiAgICAgICAgICAob25DdXN0b20pPVwiYnNNb2RhbFJlZi5oaWRlKClcIlxuICAgICAgICAgIFtzaG93QnV0dG9uc109XCJ7IGN1c3RvbTogdHJ1ZSB9XCJcbiAgICAgICAgICBbbGFiZWxzXT1cImZpbmFsU3RlcExhYmVsc1wiXG4gICAgICAgID48L2M4eS1zdGVwcGVyLWJ1dHRvbnM+XG4gICAgICA8L2Nkay1zdGVwPlxuICAgIDwvYzh5LXN0ZXBwZXI+XG4gIDwvbmctdGVtcGxhdGU+XG5cbiAgPCEtLUZhaWx1cmUgc2NlbmFyaW8tLT5cbiAgPG5nLXRlbXBsYXRlICNlcnJvck1lc3NhZ2VzUHJlc2VudD5cbiAgICA8ZGl2IGNsYXNzPVwibS0yNFwiPlxuICAgICAgPGM4eS1vcGVyYXRpb24tcmVzdWx0XG4gICAgICAgIGNsYXNzPVwibGVhZFwiXG4gICAgICAgIHR5cGU9XCJlcnJvclwiXG4gICAgICAgICpuZ0lmPVwic3RhdGUgPT09ICdyZWdpc3RyYXRpb25FcnJvcidcIlxuICAgICAgICB0ZXh0PVwie3sgJ0ZhaWxlZCB0byByZWdpc3RlcicgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICBbc2l6ZV09XCI4NFwiXG4gICAgICAgIFt2ZXJ0aWNhbF09XCJ0cnVlXCJcbiAgICAgID48L2M4eS1vcGVyYXRpb24tcmVzdWx0PlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cIm0tYi04XCJcbiAgICAgICAgKm5nRm9yPVwibGV0IG1zZyBvZiBlcnJvck1lc3NhZ2VzJCB8IGFzeW5jXCJcbiAgICAgICAgZGF0YS1jeT1cImFjdGlsaXR5LWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50LS1yZWdpc3RyYXRpb24tZXJyb3JcIlxuICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgJ3RleHQtY2VudGVyJzogc3RhdGUgPT09ICdyZWdpc3RyYXRpb25FcnJvcicsXG4gICAgICAgICAgJ2FsZXJ0IGFsZXJ0LWRhbmdlcic6IHN0YXRlID09PSAnbG9hZEVycm9yJ1xuICAgICAgICB9XCJcbiAgICAgID5cbiAgICAgICAgPHNwYW4gW2lubmVySFRNTF09XCJtc2cgfCB0cmFuc2xhdGVcIj48L3NwYW4+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwibW9kYWwtZm9vdGVyXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICAgICAgdGl0bGU9XCJ7eyAnQ2xvc2UnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIChjbGljayk9XCJic01vZGFsUmVmLmhpZGUoKVwiXG4gICAgICA+XG4gICAgICAgIHt7ICdDbG9zZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L25nLXRlbXBsYXRlPlxuPC9jOHktbW9kYWw+XG4iXX0=