UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

223 lines 42.3 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_LORIOT_REGISTRATION } from './loriot-device-registration.model'; import { LoriotErrorName, LoriotProviderService } from './loriot-provider.service'; import * as i0 from "@angular/core"; import * as i1 from "ngx-bootstrap/modal"; import * as i2 from "./loriot-provider.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 LoriotDeviceRegistrationComponent { constructor(bsModalRef, loriotService, gainsightService) { this.bsModalRef = bsModalRef; this.loriotService = loriotService; this.gainsightService = gainsightService; this.PAGING = { withTotalPages: true, pageSize: 10 }; this.form = new FormGroup({}); this.model = {}; this.protocols$ = this.getProtocols$(); this.connections$ = this.getConnections$(); this.unsubscribe$ = new Subject(); this.load$ = this.connections$.pipe(catchError((error) => of(error)), switchMap(connections => { if (connections instanceof Error && connections.name === LoriotErrorName.NoConnectivitySettingsError) { return of([connections]); } return forkJoin([ of(connections), this.protocols$.pipe(catchError((error) => of(error))) ]); }), map(results => { return results.filter(result => { return result instanceof Error; }); }), switchMap(errors => { return errors.length === 0 ? of([]) : throwError(errors); })); this.fields = [ { key: 'title', type: 'string', templateOptions: { placeholder: gettext('LORIOT LoRa'), label: gettext('Title'), required: true } }, { key: 'deveui', type: 'string', templateOptions: { placeholder: 'FEDCBA9876543210', label: gettext('Device EUI'), required: true, pattern: '^([A-F0-9]{16})$' }, validation: { messages: { pattern: gettext('Must be a valid 16 digit uppercase hexadecimal number.') } } }, { key: 'appeui', type: 'string', templateOptions: { placeholder: 'FEDCBA9876543210', 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: 'appkey', type: 'string', templateOptions: { placeholder: 'FEDCBA9876543210FEDCBA9876543210', label: gettext('Application key'), required: true, pattern: '^([a-fA-F0-9]{32})$' }, validation: { messages: { pattern: gettext('Must be a valid 32 digit hexadecimal number.') } } }, { key: 'connection', type: 'typeahead', templateOptions: { label: gettext('Connection'), required: true, c8yForOptions: this.connections$, displayProperty: 'name', valueProperties: ['name'] } }, { key: 'application', type: 'typeahead', templateOptions: { label: gettext('Application name'), required: true, placeholder: gettext('LORIOT application'), displayProperty: 'name', valueProperties: ['hexId'] }, hooks: { onInit: field => { const connectionControl = field.form.get('connection'); connectionControl.valueChanges .pipe(takeUntil(this.unsubscribe$), mergeMap(({ name }) => this.getApplications$(name))) .subscribe(apps => { field.templateOptions.c8yForOptions = of(apps); field.formControl.setValue(null); }, error => { field.form.get('application').setErrors({ application: true }); field.validators.application.message = error.message; }); } }, validators: { application: { expression: (control) => { return control.status === 'VALID'; }, message: () => '' } } }, { key: 'deviceType', type: 'typeahead', templateOptions: { label: gettext('Device protocol'), required: true, c8yForOptions: this.protocols$, displayProperty: 'name', valueProperties: ['id', 'name'] } } ]; this.registrationStepLabels = { next: gettext('Register') }; this.finalStepLabels = { back: 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.load$.subscribe(() => { this.state = 'loadSuccess'; }, errors => { this.state = 'loadError'; this.errors$.next(errors); }); } async create(event) { this.state = 'registrationPending'; const loriotDevice = this.getLoriotDeviceToSend(); try { await this.loriotService.createDevice(loriotDevice); this.state = 'registrationSuccess'; this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_LORIOT_REGISTRATION.EVENT, { result: PRODUCT_EXPERIENCE_LORIOT_REGISTRATION.RESULT.SUCCESS, component: PRODUCT_EXPERIENCE_LORIOT_REGISTRATION.COMPONENT }); } catch (error) { this.state = 'registrationError'; this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_LORIOT_REGISTRATION.EVENT, { result: PRODUCT_EXPERIENCE_LORIOT_REGISTRATION.RESULT.FAILURE, component: PRODUCT_EXPERIENCE_LORIOT_REGISTRATION.COMPONENT }); this.errors$.next([error]); } event.stepper.next(); } getLoriotDeviceToSend() { const loriotDevice = cloneDeep(this.model); loriotDevice.lnsConnectionName = this.model.connection.name; delete loriotDevice.connection; loriotDevice.appid = this.model.application.hexId; delete loriotDevice.application; return loriotDevice; } getProtocols$() { return defer(() => from(this.loriotService.getAvailableProtocols())).pipe(shareReplay(1)); } getConnections$() { return defer(() => from(this.loriotService.getConnections())).pipe(shareReplay(1)); } getApplications$(name) { return defer(() => from(this.loriotService.getApplications(name))).pipe(shareReplay(1)); } ngOnDestroy() { this.unsubscribe$.next(); this.unsubscribe$.complete(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LoriotDeviceRegistrationComponent, deps: [{ token: i1.BsModalRef }, { token: i2.LoriotProviderService }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: LoriotDeviceRegistrationComponent, selector: "c8y-loriot-registration", ngImport: i0, template: "<c8y-modal\n [title]=\"'LORIOT 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 <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 <ng-template #registrationForm>\n <c8y-stepper\n [hideStepProgress]=\"true\"\n linear\n c8y-modal-body\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 LORIOT device' | translate }}\n </p>\n <formly-form\n class=\"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 <c8y-stepper-buttons\n class=\"modal-footer d-block sticky-bottom separator-top bg-component\"\n [labels]=\"registrationStepLabels\"\n (onNext)=\"create($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 <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\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-component\"\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 <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=\"loriot-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\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: LoriotDeviceRegistrationComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-loriot-registration', template: "<c8y-modal\n [title]=\"'LORIOT 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 <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 <ng-template #registrationForm>\n <c8y-stepper\n [hideStepProgress]=\"true\"\n linear\n c8y-modal-body\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 LORIOT device' | translate }}\n </p>\n <formly-form\n class=\"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 <c8y-stepper-buttons\n class=\"modal-footer d-block sticky-bottom separator-top bg-component\"\n [labels]=\"registrationStepLabels\"\n (onNext)=\"create($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 <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\n <c8y-stepper-buttons\n class=\"sticky-bottom d-block p-t-16 p-b-16 separator-top bg-component\"\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 <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=\"loriot-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\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.LoriotProviderService }, { type: i3.GainsightService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9yaW90LWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vbG9yaW90LWRldmljZS1yZWdpc3RyYXRpb24vbG9yaW90LWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vbG9yaW90LWRldmljZS1yZWdpc3RyYXRpb24vbG9yaW90LWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQW1CLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzVELE9BQU8sRUFBYyxnQkFBZ0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUU1RSxPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM1QyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxFQUFFLGVBQWUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN2RixPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RixPQUFPLEVBR0wsc0NBQXNDLEVBQ3ZDLE1BQU0sb0NBQW9DLENBQUM7QUFDNUMsT0FBTyxFQUFFLGVBQWUsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7Ozs7OztBQWNuRixNQUFNLE9BQU8saUNBQWlDO0lBd0s1QyxZQUNTLFVBQXNCLEVBQ3JCLGFBQW9DLEVBQ3BDLGdCQUFrQztRQUZuQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FB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RixDQUFDO0lBRUQsZUFBZTtRQUNiLE9BQU8sS0FBSyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDckYsQ0FBQztJQUVELGdCQUFnQixDQUFDLElBQUk7UUFDbkIsT0FBTyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDMUYsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDL0IsQ0FBQzsrR0F0T1UsaUNBQWlDO21HQUFqQyxpQ0FBaUMsK0RDNUI5QywwMkdBMEdBOzs0RkQ5RWEsaUNBQWlDO2tCQUo3QyxTQUFTOytCQUNFLHlCQUF5QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENka1N0ZXAgfSBmcm9tICdAYW5ndWxhci9jZGsvc3RlcHBlcic7XG5pbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQzh5U3RlcHBlciwgR2FpbnNpZ2h0U2VydmljZSwgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgRm9ybWx5RmllbGRDb25maWcgfSBmcm9tICdAbmd4LWZvcm1seS9jb3JlJztcbmltcG9ydCB7IGNsb25lRGVlcCwgdW5pcSB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBCc01vZGFsUmVmIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGRlZmVyLCBmb3JrSm9pbiwgZnJvbSwgb2YsIFN1YmplY3QsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgbWVyZ2VNYXAsIHNoYXJlUmVwbGF5LCBzd2l0Y2hNYXAsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIExvcmlvdERldmljZSxcbiAgTG9yaW90RGV2aWNlRm9ybWx5LFxuICBQUk9EVUNUX0VYUEVSSUVOQ0VfTE9SSU9UX1JFR0lTVFJBVElPTlxufSBmcm9tICcuL2xvcmlvdC1kZXZpY2UtcmVnaXN0cmF0aW9uLm1vZGVsJztcbmltcG9ydCB7IExvcmlvdEVycm9yTmFtZSwgTG9yaW90UHJvdmlkZXJTZXJ2aWNlIH0gZnJvbSAnLi9sb3Jpb3QtcHJvdmlkZXIuc2VydmljZSc7XG5cbnR5cGUgTG9yaW90U3RhdGUgPVxuICB8ICdsb2FkUGVuZGluZydcbiAgfCAnbG9hZFN1Y2Nlc3MnXG4gIHwgJ2xvYWRFcnJvcidcbiAgfCAncmVnaXN0cmF0aW9uUGVuZGluZydcbiAgfCAncmVnaXN0cmF0aW9uU3VjY2VzcydcbiAgfCAncmVnaXN0cmF0aW9uRXJyb3InO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktbG9yaW90LXJlZ2lzdHJhdGlvbicsXG4gIHRlbXBsYXRlVXJsOiAnbG9yaW90LWRldmljZS1yZWdpc3RyYXRpb24uY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIExvcmlvdERldmljZVJlZ2lzdHJhdGlvbkNvbXBvbmVudCB7XG4gIHN0ZXBwZXI6IEM4eVN0ZXBwZXI7XG4gIHJlYWRvbmx5IFBBR0lORzogb2JqZWN0ID0ge1xuICAgIHdpdGhUb3RhbFBhZ2VzOiB0cnVlLFxuICAgIHBhZ2VTaXplOiAxMFxuICB9O1xuXG4gIGZvcm0gPSBuZXcgRm9ybUdyb3VwKHt9KTtcbiAgbW9kZWw6IExvcmlvdERldmljZUZvcm1seSA9IHt9IGFzIGFueTtcbiAgcHJvdG9jb2xzJCA9IHRoaXMuZ2V0UHJvdG9jb2xzJCgpO1xuICBjb25uZWN0aW9ucyQgPSB0aGlzLmdldENvbm5lY3Rpb25zJCgpO1xuICB1bnN1YnNjcmliZSQ6IFN1YmplY3Q8dm9pZD4gPSBuZXcgU3ViamVjdCgpO1xuXG4gIGxvYWQkID0gdGhpcy5jb25uZWN0aW9ucyQucGlwZShcbiAgICBjYXRjaEVycm9yKChlcnJvcjogRXJyb3IpID0+IG9mKGVycm9yKSksXG4gICAgc3dpdGNoTWFwKGNvbm5lY3Rpb25zID0+IHtcbiAgICAgIGlmIChcbiAgICAgICAgY29ubmVjdGlvbnMgaW5zdGFuY2VvZiBFcnJvciAmJlxuICAgICAgICBjb25uZWN0aW9ucy5uYW1lID09PSBMb3Jpb3RFcnJvck5hbWUuTm9Db25uZWN0aXZpdHlTZXR0aW5nc0Vycm9yXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIG9mKFtjb25uZWN0aW9uc10pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZvcmtKb2luKFtcbiAgICAgICAgb2YoY29ubmVjdGlvbnMpLFxuICAgICAgICB0aGlzLnByb3RvY29scyQucGlwZShjYXRjaEVycm9yKChlcnJvcjogRXJyb3IpID0+IG9mKGVycm9yKSkpXG4gICAgICBdKTtcbiAgICB9KSxcbiAgICBtYXAocmVzdWx0cyA9PiB7XG4gICAgICByZXR1cm4gcmVzdWx0cy5maWx0ZXIocmVzdWx0ID0+IHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCBpbnN0YW5jZW9mIEVycm9yO1xuICAgICAgfSk7XG4gICAgfSksXG4gICAgc3dpdGNoTWFwKGVycm9ycyA9PiB7XG4gICAgICByZXR1cm4gZXJyb3JzLmxlbmd0aCA9PT0gMCA/IG9mKFtdKSA6IHRocm93RXJyb3IoZXJyb3JzKTtcbiAgICB9KVxuICApO1xuXG4gIGZpZWxkczogRm9ybWx5RmllbGRDb25maWdbXSA9IFtcbiAgICB7XG4gICAgICBrZXk6ICd0aXRsZScsXG4gICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgIHRlbXBsYXRlT3B0aW9uczoge1xuICAgICAgICBwbGFjZWhvbGRlcjogZ2V0dGV4dCgnTE9SSU9UIExvUmEnKSxcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ1RpdGxlJyksXG4gICAgICAgIHJlcXVpcmVkOiB0cnVlXG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBrZXk6ICdkZXZldWknLFxuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgcGxhY2Vob2xkZXI6ICdGRURDQkE5ODc2NTQzMjEwJyxcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ0RldmljZSBFVUknKSxcbiAgICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgICAgIHBhdHRlcm46ICdeKFtBLUYwLTldezE2fSkkJ1xuICAgICAgfSxcbiAgICAgIHZhbGlkYXRpb246IHtcbiAgICAgICAgbWVzc2FnZXM6IHtcbiAgICAgICAgICBwYXR0ZXJuOiBnZXR0ZXh0KCdNdXN0IGJlIGEgdmFsaWQgMTYgZGlnaXQgdXBwZXJjYXNlIGhleGFkZWNpbWFsIG51bWJlci4nKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBrZXk6ICdhcHBldWknLFxuICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgcGxhY2Vob2xkZXI6ICdGRURDQkE5ODc2NTQzMjEwJyxcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ0FwcGxpY2F0aW9uIEVVSScpLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgcGF0dGVybjogJ14oW2EtZkEtRjAtOV17MTZ9KSQnXG4gICAgICB9LFxuICAgICAgdmFsaWRhdGlvbjoge1xuICAgICAgICBtZXNzYWdlczoge1xuICAgICAgICAgIHBhdHRlcm46IGdldHRleHQoJ011c3QgYmUgYSB2YWxpZCAxNiBkaWdpdCBoZXhhZGVjaW1hbCBudW1iZXIuJylcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAge1xuICAgICAga2V5OiAnYXBwa2V5JyxcbiAgICAgIHR5cGU6ICdzdHJpbmcnLFxuICAgICAgdGVtcGxhdGVPcHRpb25zOiB7XG4gICAgICAgIHBsYWNlaG9sZGVyOiAnRkVEQ0JBOTg3NjU0MzIxMEZFRENCQTk4NzY1NDMyMTAnLFxuICAgICAgICBsYWJlbDogZ2V0dGV4dCgnQXBwbGljYXRpb24ga2V5JyksXG4gICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICBwYXR0ZXJuOiAnXihbYS1mQS1GMC05XXszMn0pJCdcbiAgICAgIH0sXG4gICAgICB2YWxpZGF0aW9uOiB7XG4gICAgICAgIG1lc3NhZ2VzOiB7XG4gICAgICAgICAgcGF0dGVybjogZ2V0dGV4dCgnTXVzdCBiZSBhIHZhbGlkIDMyIGRpZ2l0IGhleGFkZWNpbWFsIG51bWJlci4nKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBrZXk6ICdjb25uZWN0aW9uJyxcbiAgICAgIHR5cGU6ICd0eXBlYWhlYWQnLFxuICAgICAgdGVtcGxhdGVPcHRpb25zOiB7XG4gICAgICAgIGxhYmVsOiBnZXR0ZXh0KCdDb25uZWN0aW9uJyksXG4gICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICBjOHlGb3JPcHRpb25zOiB0aGlzLmNvbm5lY3Rpb25zJCxcbiAgICAgICAgZGlzcGxheVByb3BlcnR5OiAnbmFtZScsXG4gICAgICAgIHZhbHVlUHJvcGVydGllczogWyduYW1lJ11cbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGtleTogJ2FwcGxpY2F0aW9uJyxcbiAgICAgIHR5cGU6ICd0eXBlYWhlYWQnLFxuICAgICAgdGVtcGxhdGVPcHRpb25zOiB7XG4gICAgICAgIGxhYmVsOiBnZXR0ZXh0KCdBcHBsaWNhdGlvbiBuYW1lJyksXG4gICAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgICAgICBwbGFjZWhvbGRlcjogZ2V0dGV4dCgnTE9SSU9UIGFwcGxpY2F0aW9uJyksXG4gICAgICAgIGRpc3BsYXlQcm9wZXJ0eTogJ25hbWUnLFxuICAgICAgICB2YWx1ZVByb3BlcnRpZXM6IFsnaGV4SWQnXVxuICAgICAgfSxcbiAgICAgIGhvb2tzOiB7XG4gICAgICAgIG9uSW5pdDogZmllbGQgPT4ge1xuICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb25Db250cm9sID0gZmllbGQuZm9ybS5nZXQoJ2Nvbm5lY3Rpb24nKTtcbiAgICAgICAgICBjb25uZWN0aW9uQ29udHJvbC52YWx1ZUNoYW5nZXNcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy51bnN1YnNjcmliZSQpLFxuICAgICAgICAgICAgICBtZXJnZU1hcCgoeyBuYW1lIH0pID0+IHRoaXMuZ2V0QXBwbGljYXRpb25zJChuYW1lKSlcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgIGFwcHMgPT4ge1xuICAgICAgICAgICAgICAgIGZpZWxkLnRlbXBsYXRlT3B0aW9ucy5jOHlGb3JPcHRpb25zID0gb2YoYXBwcyk7XG4gICAgICAgICAgICAgICAgZmllbGQuZm9ybUNvbnRyb2wuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBmaWVsZC5mb3JtLmdldCgnYXBwbGljYXRpb24nKS5zZXRFcnJvcnMoeyBhcHBsaWNhdGlvbjogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICBmaWVsZC52YWxpZGF0b3JzLmFwcGxpY2F0aW9uLm1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdmFsaWRhdG9yczoge1xuICAgICAgICBhcHBsaWNhdGlvbjoge1xuICAgICAgICAgIGV4cHJlc3Npb246IChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBjb250cm9sLnN0YXR1cyA9PT0gJ1ZBTElEJztcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1lc3NhZ2U6ICgpID0+ICcnXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGtleTogJ2RldmljZVR5cGUnLFxuICAgICAgdHlwZTogJ3R5cGVhaGVhZCcsXG4gICAgICB0ZW1wbGF0ZU9wdGlvbnM6IHtcbiAgICAgICAgbGFiZWw6IGdldHRleHQoJ0RldmljZSBwcm90b2NvbCcpLFxuICAgICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICAgICAgYzh5Rm9yT3B0aW9uczogdGhpcy5wcm90b2NvbHMkLFxuICAgICAgICBkaXNwbGF5UHJvcGVydHk6ICduYW1lJyxcbiAgICAgICAgdmFsdWVQcm9wZXJ0aWVzOiBbJ2lkJywgJ25hbWUnXVxuICAgICAgfVxuICAgIH1cbiAgXTtcblxuICByZWdpc3RyYXRpb25TdGVwTGFiZWxzID0ge1xuICAgIG5leHQ6IGdldHRleHQoJ1JlZ2lzdGVyJylcbiAgfTtcbiAgZmluYWxTdGVwTGFiZWxzID0ge1xuICAgIGJhY2s6IGdldHRleHQoJ0Nsb3NlJylcbiAgfTtcblxuICBzdGF0ZTogTG9yaW90U3RhdGUgPSAnbG9hZFBlbmRpbmcnO1xuICBlcnJvcnMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxFcnJvcltdPihbXSk7XG4gIGVycm9yTWVzc2FnZXMkID0gdGhpcy5lcnJvcnMkLnBpcGUoXG4gICAgbWFwKGVycm9ycyA9PiBlcnJvcnMubWFwKGVycm9yID0+IGVycm9yLm1lc3NhZ2UpKSxcbiAgICBtYXAobWVzc2FnZXMgPT4gdW5pcShtZXNzYWdlcykpXG4gICk7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyBic01vZGFsUmVmOiBCc01vZGFsUmVmLFxuICAgIHByaXZhdGUgbG9yaW90U2VydmljZTogTG9yaW90UHJvdmlkZXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgZ2FpbnNpZ2h0U2VydmljZTogR2FpbnNpZ2h0U2VydmljZVxuICApIHtcbiAgICB0aGlzLmxvYWQkLnN1YnNjcmliZShcbiAgICAgICgpID0+IHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9ICdsb2FkU3VjY2Vzcyc7XG4gICAgICB9LFxuICAgICAgZXJyb3JzID0+IHtcbiAgICAgICAgdGhpcy5zdGF0ZSA9ICdsb2FkRXJyb3InO1xuICAgICAgICB0aGlzLmVycm9ycyQubmV4dChlcnJvcnMpO1xuICAgICAgfVxuICAgICk7XG4gIH1cblxuICBhc3luYyBjcmVhdGUoZXZlbnQ6IHsgc3RlcHBlcjogQzh5U3RlcHBlcjsgc3RlcDogQ2RrU3RlcCB9KSB7XG4gICAgdGhpcy5zdGF0ZSA9ICdyZWdpc3RyYXRpb25QZW5kaW5nJztcbiAgICBjb25zdCBsb3Jpb3REZXZpY2UgPSB0aGlzLmdldExvcmlvdERldmljZVRvU2VuZCgpO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCB0aGlzLmxvcmlvdFNlcnZpY2UuY3JlYXRlRGV2aWNlKGxvcmlvdERldmljZSk7XG4gICAgICB0aGlzLnN0YXRlID0gJ3JlZ2lzdHJhdGlvblN1Y2Nlc3MnO1xuICAgICAgdGhpcy5nYWluc2lnaHRTZXJ2aWNlLnRyaWdnZXJFdmVudChQUk9EVUNUX0VYUEVSSUVOQ0VfTE9SSU9UX1JFR0lTVFJBVElPTi5FVkVOVCwge1xuICAgICAgICByZXN1bHQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9MT1JJT1RfUkVHSVNUUkFUSU9OLlJFU1VMVC5TVUNDRVNTLFxuICAgICAgICBjb21wb25lbnQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9MT1JJT1RfUkVHSVNUUkFUSU9OLkNPTVBPTkVOVFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuc3RhdGUgPSAncmVnaXN0cmF0aW9uRXJyb3InO1xuICAgICAgdGhpcy5nYWluc2lnaHRTZXJ2aWNlLnRyaWdnZXJFdmVudChQUk9EVUNUX0VYUEVSSUVOQ0VfTE9SSU9UX1JFR0lTVFJBVElPTi5FVkVOVCwge1xuICAgICAgICByZXN1bHQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9MT1JJT1RfUkVHSVNUUkFUSU9OLlJFU1VMVC5GQUlMVVJFLFxuICAgICAgICBjb21wb25lbnQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9MT1JJT1RfUkVHSVNUUkFUSU9OLkNPTVBPTkVOVFxuICAgICAgfSk7XG4gICAgICB0aGlzLmVycm9ycyQubmV4dChbZXJyb3JdKTtcbiAgICB9XG5cbiAgICBldmVudC5zdGVwcGVyLm5leHQoKTtcbiAgfVxuXG4gIGdldExvcmlvdERldmljZVRvU2VuZCgpIHtcbiAgICBjb25zdCBsb3Jpb3REZXZpY2U6IExvcmlvdERldmljZSA9IGNsb25lRGVlcCh0aGlzLm1vZGVsKTtcbiAgICBsb3Jpb3REZXZpY2UubG5zQ29ubmVjdGlvbk5hbWUgPSB0aGlzLm1vZGVsLmNvbm5lY3Rpb24ubmFtZTtcbiAgICBkZWxldGUgKGxvcmlvdERldmljZSBhcyBhbnkpLmNvbm5lY3Rpb247XG4gICAgbG9yaW90RGV2aWNlLmFwcGlkID0gdGhpcy5tb2RlbC5hcHBsaWNhdGlvbi5oZXhJZDtcbiAgICBkZWxldGUgKGxvcmlvdERldmljZSBhcyBhbnkpLmFwcGxpY2F0aW9uO1xuICAgIHJldHVybiBsb3Jpb3REZXZpY2U7XG4gIH1cblxuICBnZXRQcm90b2NvbHMkKCkge1xuICAgIHJldHVybiBkZWZlcigoKSA9PiBmcm9tKHRoaXMubG9yaW90U2VydmljZS5nZXRBdmFpbGFibGVQcm90b2NvbHMoKSkpLnBpcGUoc2hhcmVSZXBsYXkoMSkpO1xuICB9XG5cbiAgZ2V0Q29ubmVjdGlvbnMkKCkge1xuICAgIHJldHVybiBkZWZlcigoKSA9PiBmcm9tKHRoaXMubG9yaW90U2VydmljZS5nZXRDb25uZWN0aW9ucygpKSkucGlwZShzaGFyZVJlcGxheSgxKSk7XG4gIH1cblxuICBnZXRBcHBsaWNhdGlvbnMkKG5hbWUpIHtcbiAgICByZXR1cm4gZGVmZXIoKCkgPT4gZnJvbSh0aGlzLmxvcmlvdFNlcnZpY2UuZ2V0QXBwbGljYXRpb25zKG5hbWUpKSkucGlwZShzaGFyZVJlcGxheSgxKSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLnVuc3Vic2NyaWJlJC5uZXh0KCk7XG4gICAgdGhpcy51bnN1YnNjcmliZSQuY29tcGxldGUoKTtcbiAgfVxufVxuIiwiPGM4eS1tb2RhbFxuICBbdGl0bGVdPVwiJ0xPUklPVCByZWdpc3RyYXRpb24nIHwgdHJhbnNsYXRlXCJcbiAgW2hlYWRlckNsYXNzZXNdPVwiJ2RpYWxvZy1oZWFkZXInXCJcbiAgW2N1c3RvbUZvb3Rlcl09XCJ0cnVlXCJcbj5cbiAgPG5nLWNvbnRhaW5lciBjOHktbW9kYWwtdGl0bGU+XG4gICAgPHNwYW4gW2M4eUljb25dPVwiJ2M4eS1kZXZpY2UtY29ubmVjdCdcIj48L3NwYW4+XG4gIDwvbmctY29udGFpbmVyPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwic3RhdGUgPT09ICdsb2FkUGVuZGluZyc7IGVsc2UgcmVnaXN0cmF0aW9uRm9ybVwiPlxuICAgIDxkaXYgY2xhc3M9XCJwLTE2IHRleHQtY2VudGVyXCI+XG4gICAgICA8Yzh5LWxvYWRpbmc+PC9jOHktbG9hZGluZz5cbiAgICA8L2Rpdj5cbiAgPC9uZy1jb250YWluZXI+XG5cbiAgPG5nLXRlbXBsYXRlICNyZWdpc3RyYXRpb25Gb3JtPlxuICAgIDxjOHktc3RlcHBlclxuICAgICAgW2hpZGVTdGVwUHJvZ3Jlc3NdPVwidHJ1ZVwiXG4gICAgICBsaW5lYXJcbiAgICAgIGM4eS1tb2RhbC1ib2R5XG4gICAgICAqbmdJZj1cIihlcnJvck1lc3NhZ2VzJCB8IGFzeW5jKS5sZW5ndGggPT09IDA7IGVsc2UgZXJyb3JNZXNzYWdlc1ByZXNlbnRcIlxuICAgID5cbiAgICAgIDxjZGstc3RlcCBbc3RlcENvbnRyb2xdPVwiZm9ybVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC1iLTE2XCI+XG4gICAgICAgICAgPHAgY2xhc3M9XCJtb2RhbC1zdWJ0aXRsZSBzdGlja3ktdG9wXCI+XG4gICAgICAgICAgICB7eyAnUmVnaXN0ZXIgYSBzaW5nbGUgTE9SSU9UIGRldmljZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L3A+XG4gICAgICAgICAgPGZvcm1seS1mb3JtXG4gICAgICAgICAgICBjbGFzcz1cImQtYmxvY2sgcC1sLTI0IHAtci0yNCBwLXQtMTZcIlxuICAgICAgICAgICAgW2Zvcm1dPVwiZm9ybVwiXG4gICAgICAgICAgICBbZmllbGRzXT1cImZpZWxkc1wiXG4gICAgICAgICAgICBbbW9kZWxdPVwibW9kZWxcIlxuICAgICAgICAgID48L2Zvcm1seS1mb3JtPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGM4eS1zdGVwcGVyLWJ1dHRvbnNcbiAgICAgICAgICBjbGFzcz1cIm1vZGFsLWZvb3RlciBkLWJsb2NrIHN0aWNreS1ib3R0b20gc2VwYXJhdG9yLXRvcCBiZy1jb21wb25lbnRcIlxuICAgICAgICAgIFtsYWJlbHNdPVwicmVnaXN0cmF0aW9uU3RlcExhYmVsc1wiXG4gICAgICAgICAgKG9uTmV4dCk9XCJjcmVhdGUoJGV2ZW50KVwiXG4gICAgICAgICAgKG9uQ2FuY2VsKT1cImJzTW9kYWxSZWYuaGlkZSgpXCJcbiAgICAgICAgICBbc2hvd0J1dHRvbnNdPVwieyBjYW5jZWw6IHRydWUsIG5leHQ6IHRydWUgfVwiXG4gICAgICAgICAgW3BlbmRpbmddPVwic3RhdGUgPT09ICdyZWdpc3RyYXRpb25QZW5kaW5nJ1wiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cIiFmb3JtLnZhbGlkXCJcbiAgICAgICAgPjwvYzh5LXN0ZXBwZXItYnV0dG9ucz5cbiAgICAgIDwvY2RrLXN0ZXA+XG4gICAgICA8Y2RrLXN0ZXAgc3RhdGU9XCJmaW5hbFwiPlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgY2xhc3M9XCJwLTE2IHRleHQtY2VudGVyXCJcbiAgICAgICAgICAqbmdJZj1cInN0YXRlID09PSAncmVnaXN0cmF0aW9uUGVuZGluZydcIlxuICAgICAgICA+XG4gICAgICAgICAgPGM4eS1sb2FkaW5nPjwvYzh5LWxvYWRpbmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibS0yNFwiPlxuICAgICAgICAgIDxjOHktb3BlcmF0aW9uLXJlc3VsdFxuICAgICAgICAgICAgY2xhc3M9XCJsZWFkIG0tYi0wXCJcbiAgICAgICAgICAgIHR5cGU9XCJzdWNjZXNzXCJcbiAgICAgICAgICAgICpuZ0lmPVwic3RhdGUgPT09ICdyZWdpc3RyYXRpb25TdWNjZXNzJ1wiXG4gICAgICAgICAgICB0ZXh0PVwie3sgJ0RldmljZSByZWdpc3RlcmVkJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICBbc2l6ZV09XCI4NFwiXG4gICAgICAgICAgICBbdmVydGljYWxdPVwidHJ1ZVwiXG4gICAgICAgICAgPjwvYzh5LW9wZXJhdGlvbi1yZXN1bHQ+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxjOHktc3RlcHBlci1idXR0b25zXG4gICAgICAgICAgY2xhc3M9XCJzdGlja3ktYm90dG9tIGQtYmxvY2sgcC10LTE2IHAtYi0xNiBzZXBhcmF0b3ItdG9wIGJnLWNvbXBvbmVudFwiXG4gICAgICAgICAgKG9uQ3VzdG9tKT1cImJzTW9kYWxSZWYuaGlkZSgpXCJcbiAgICAgICAgICBbc2hvd0J1dHRvbnNdPVwieyBjdXN0b206IHRydWUgfVwiXG4gICAgICAgICAgW2xhYmVsc109XCJmaW5hbFN0ZXBMYWJlbHNcIlxuICAgICAgICA+PC9jOHktc3RlcHBlci1idXR0b25zPlxuICAgICAgPC9jZGstc3RlcD5cbiAgICA8L2M4eS1zdGVwcGVyPlxuICA8L25nLXRlbXBsYXRlPlxuXG4gIDxuZy10ZW1wbGF0ZSAjZXJyb3JNZXNzYWdlc1ByZXNlbnQ+XG4gICAgPGRpdiBjbGFzcz1cIm0tMjRcIj5cbiAgICAgIDxjOHktb3BlcmF0aW9uLXJlc3VsdFxuICAgICAgICBjbGFzcz1cImxlYWRcIlxuICAgICAgICB0eXBlPVwiZXJyb3JcIlxuICAgICAgICAqbmdJZj1cInN0YXRlID09PSAncmVnaXN0cmF0aW9uRXJyb3InXCJcbiAgICAgICAgdGV4dD1cInt7ICdGYWlsZWQgdG8gcmVnaXN0ZXInIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgW3NpemVdPVwiODRcIlxuICAgICAgICBbdmVydGljYWxdPVwidHJ1ZVwiXG4gICAgICA+PC9jOHktb3BlcmF0aW9uLXJlc3VsdD5cbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJtLWItOFwiXG4gICAgICAgICpuZ0Zvcj1cImxldCBtc2cgb2YgZXJyb3JNZXNzYWdlcyQgfCBhc3luY1wiXG4gICAgICAgIGRhdGEtY3k9XCJsb3Jpb3QtZGV2aWNlLXJlZ2lzdHJhdGlvbi5jb21wb25lbnQtLXJlZ2lzdHJhdGlvbi1lcnJvclwiXG4gICAgICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgICAndGV4dC1jZW50ZXInOiBzdGF0ZSA9PT0gJ3JlZ2lzdHJhdGlvbkVycm9yJyxcbiAgICAgICAgICAnYWxlcnQgYWxlcnQtZGFuZ2VyJzogc3RhdGUgPT09ICdsb2FkRXJyb3InXG4gICAgICAgIH1cIlxuICAgICAgPlxuICAgICAgICA8c3BhbiBbaW5uZXJIVE1MXT1cIm1zZyB8IHRyYW5zbGF0ZVwiPjwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiBjbGFzcz1cIm1vZGFsLWZvb3RlclwiPlxuICAgICAgPGJ1dHRvblxuICAgICAgICBjbGFzcz1cImJ0biBidG4tZGVmYXVsdFwiXG4gICAgICAgIHRpdGxlPVwie3sgJ0Nsb3NlJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAoY2xpY2spPVwiYnNNb2RhbFJlZi5oaWRlKClcIlxuICAgICAgPlxuICAgICAgICB7eyAnQ2xvc2UnIHwgdHJhbnNsYXRlIH19XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9uZy10ZW1wbGF0ZT5cbjwvYzh5LW1vZGFsPlxuIl19