UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

230 lines 38.7 kB
import { Injectable } from '@angular/core'; import { InventoryService, OperationService, OperationStatus, QueriesUtil } from '@c8y/client'; import { AlertService, gettext } from '@c8y/ngx-components'; import { get, isEmpty, isNil, keyBy, keys, mapValues, omitBy, pickBy, sortBy, toArray, uniqBy } from 'lodash-es'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/client"; import * as i2 from "@c8y/ngx-components"; export class DeviceProfileService { constructor(inventoryService, operationService, alertService) { this.inventoryService = inventoryService; this.operationService = operationService; this.alertService = alertService; this.dateFrom = new Date(0); this.dateTo = new Date(Date.now() + 86400000); // 1 day in the future this.NOT_INSTALLED_WARNING = gettext('Not installed on the device'); this.VERSION_MISSMATCH_WARNING = gettext('Version mismatch'); this.SAME_URL_WARNING = gettext('Installed configuration has the same URL but different name or type than the one in the profile'); this.queriesUtil = new QueriesUtil(); } createDeviceProfile(deviceProfile) { if (get(deviceProfile, 'c8y_Filter.type') === '') { delete deviceProfile.c8y_Filter.type; } return this.inventoryService.create(deviceProfile); } /** * Determines the available device profiles for a given device by considering device type * and the supported software types declared by the devices. Because of limitations in the * Inventory Query API the methods return profile that contain at least one of the supported * software types and omits profiles having only non-supported software types. Resulting device * profiles need to be further filtered on the client side to exclude the ones that contain * non-supported software types next to the supported ones. * * @param device A device MO * @param name Optional device profile name filter * @returns Candidate device profiles that contain at least on software with supported type. */ getDeviceProfilesByDevice(device, name = null) { const deviceTypeFilter = { __or: [ { 'c8y_Filter.type': device.type }, { 'c8y_Filter.type': '' }, { __not: { __has: 'c8y_Filter.type' } } ] }; let softwareTypeFilter = {}; if (!isEmpty(device.c8y_SupportedSoftwareTypes)) { softwareTypeFilter = { __hasany: device.c8y_SupportedSoftwareTypes.map((type) => `softwareType!${type}`) }; } let query = this.queriesUtil.addAndFilter(deviceTypeFilter, softwareTypeFilter); let profileNameFilter = {}; if (!isEmpty(name)) { profileNameFilter = { name: `*${name}*` }; } query = this.queriesUtil.addAndFilter(query, profileNameFilter); return this.getDeviceProfiles(query); } /** * @deprecated Use `getDeviceProfilesByDevice` instead as it also considers the supported software types. */ getDeviceProfilesByDeviceType(deviceType) { const deviceTypeFilter = { __or: [ { 'c8y_Filter.type': deviceType }, { 'c8y_Filter.type': '' }, { __not: { __has: 'c8y_Filter.type' } } ] }; return this.getDeviceProfiles(deviceTypeFilter); } getDeviceProfiles(andQuery) { let query = { type: 'c8y_Profile' }; const filter = { pageSize: 100, withTotalPages: true }; query = this.queriesUtil.addAndFilter(query, andQuery || {}); return this.inventoryService.listQuery(query, filter); } async getProfileOperation(deviceId) { const filter = { deviceId, fragmentType: 'c8y_DeviceProfile', dateFrom: this.dateFrom.toISOString(), dateTo: this.dateTo.toISOString(), revert: true, pageSize: 1 }; const operation = (await this.operationService.list(filter)).data[0]; return operation && operation.status !== OperationStatus.SUCCESSFUL ? operation : undefined; } async createProfileOperation(device, deviceProfile) { let operation; const operationCfg = { deviceId: device.id, profileId: deviceProfile.id, profileName: deviceProfile.name, c8y_DeviceProfile: deviceProfile.c8y_DeviceProfile, description: `Assign device profile ${deviceProfile.name} to device ${device.name}` }; try { const { data } = await this.operationService.create(operationCfg); operation = data; } catch (ex) { this.alertService.addServerFailure(ex); } return operation; } getFirmwareItems(device, selectedProfile) { const deviceFirmware = device.c8y_Firmware; const profileFirmware = get(selectedProfile, 'c8y_DeviceProfile.firmware'); const deviceItems = []; const profileItems = []; if (deviceFirmware) { deviceItems.push(deviceFirmware); } if (profileFirmware) { profileItems.push(profileFirmware); } return this.createProfileComparison(deviceItems, profileItems, 'name', 'version', null, this.getAlert('firmware')); } getSoftwareItems(device, selectedProfile) { const deviceSoftware = device.c8y_SoftwareList; const profileSoftware = get(selectedProfile, 'c8y_DeviceProfile.software'); return this.createProfileComparison(deviceSoftware, profileSoftware, 'name', 'version', 'softwareType', this.getAlert('software')); } getConfigurationItems(device, selectedProfile) { const deviceConfiguration = []; Object.keys(device).forEach(key => { if (key.slice(0, 18) === 'c8y_Configuration_') { deviceConfiguration.push(device[key]); } }); const profileConfiguration = get(selectedProfile, 'c8y_DeviceProfile.configuration'); return this.createProfileComparison(deviceConfiguration, profileConfiguration, 'url', null, 'type', this.getAlert('configuration')); } /** * Aligns device profile managed object's `softwareType!*` fragments to the software items * included in the device profile. Removes obsolete software type fragments and adds new. * * @param profilePartial The device profile managed object which `softwareType!*` fragments will be adjusted. * @returns The adjusted device profile managed object. */ alignSoftwareTypeFragments(profilePartial, profile) { if (!profilePartial?.c8y_DeviceProfile?.software || !profile) { return profilePartial; } const removedSoftwareTypes = mapValues(omitBy(profile, (_, key) => typeof key === 'string' && !key.startsWith('softwareType!')), () => null); const softwareTypesToAdd = mapValues(keyBy(uniqBy(profilePartial.c8y_DeviceProfile.software, 'softwareType'), (profile) => `softwareType!${profile.softwareType}`), () => ({})); const result = { ...profilePartial, ...removedSoftwareTypes, ...softwareTypesToAdd }; return result; } getSoftwareTypes(profile) { return keys(pickBy(profile, (_, key) => typeof key === 'string' && key.startsWith('softwareType!'))).map(softwareType => softwareType.substr('softwareType!'.length)); } getAlert(itemType) { const notInstalled = (comparisionResult) => { return !comparisionResult.device ? this.NOT_INSTALLED_WARNING : ''; }; switch (itemType) { case 'firmware': case 'software': return (comparisionResult) => { return comparisionResult.device && comparisionResult.profile && comparisionResult.device.itemDetails !== comparisionResult.profile.itemDetails ? this.VERSION_MISSMATCH_WARNING : notInstalled(comparisionResult); }; case 'configuration': return (comparisionResult) => { return comparisionResult.device && comparisionResult.profile && (comparisionResult.device.itemName !== comparisionResult.profile.itemName || comparisionResult.device.itemDetails !== comparisionResult.profile.itemDetails) ? this.SAME_URL_WARNING : notInstalled(comparisionResult); }; default: return notInstalled; } } createProfileComparison(deviceItems = [], profileItems = [], mergeByProperty, propertyNameWithDetails, propertyNameWithType, getAlert) { const comparisonObj = this.createProfileComparisonFromDeviceItems(deviceItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType); const extendedComparisonObj = this.extendProfileComparisonWithProfileItems(comparisonObj, profileItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType, getAlert); return sortBy(toArray(extendedComparisonObj), 'name'); } createProfileComparisonFromDeviceItems(deviceItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType) { return deviceItems.reduce((comapritionItem, deviceItem) => Object.assign(comapritionItem, { [deviceItem[mergeByProperty]]: { device: omitBy({ itemName: deviceItem.name, itemDetails: deviceItem[propertyNameWithDetails], itemType: deviceItem[propertyNameWithType], itemUrl: deviceItem.url }, isNil), profile: undefined } }), {}); } extendProfileComparisonWithProfileItems(comparisonObj, profileItems, mergeByProperty, propertyNameWithDetails, propertyNameWithType, getAlert) { profileItems.forEach(profileItem => { const comparisionResult = { profile: omitBy({ itemName: profileItem.name, itemDetails: profileItem[propertyNameWithDetails], itemType: profileItem[propertyNameWithType], itemUrl: profileItem.url }, isNil), device: comparisonObj[profileItem[mergeByProperty]] ? comparisonObj[profileItem[mergeByProperty]].device : undefined }; comparisionResult.comparisonAlert = getAlert(comparisionResult); comparisonObj[profileItem[mergeByProperty]] = comparisionResult; }); return comparisonObj; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProfileService, deps: [{ token: i1.InventoryService }, { token: i1.OperationService }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProfileService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceProfileService, decorators: [{ type: Injectable }], ctorParameters: () => [{ type: i1.InventoryService }, { type: i1.OperationService }, { type: i2.AlertService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLXByb2ZpbGUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2RldmljZS1wcm9maWxlL2RldmljZS1wcm9maWxlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMzQyxPQUFPLEVBRUwsZ0JBQWdCLEVBR2hCLGdCQUFnQixFQUNoQixlQUFlLEVBQ2YsV0FBVyxFQUNaLE1BQU0sYUFBYSxDQUFDO0FBQ3JCLE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDNUQsT0FBTyxFQUNMLEdBQUcsRUFDSCxPQUFPLEVBQ1AsS0FBSyxFQUNMLEtBQUssRUFDTCxJQUFJLEVBQ0osU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sTUFBTSxFQUNOLE9BQU8sRUFDUCxNQUFNLEVBQ1AsTUFBTSxXQUFXLENBQUM7Ozs7QUFTbkIsTUFBTSxPQUFPLG9CQUFvQjtJQVcvQixZQUNVLGdCQUFrQyxFQUNsQyxnQkFBa0MsRUFDbEMsWUFBMEI7UUFGMUIscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ2xDLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBYjNCLGFBQVEsR0FBRyxJQUFJLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixXQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsc0JBQXNCO1FBR2pFLDBCQUFxQixHQUFHLE9BQU8sQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO1FBQy9ELDhCQUF5QixHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1FBQ3hELHFCQUFnQixHQUFHLE9BQU8sQ0FDaEMsaUdBQWlHLENBQ2xHLENBQUM7UUFPQSxJQUFJLENB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Ozs0RkFBcEIsb0JBQW9CO2tCQURoQyxVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgSU1hbmFnZWRPYmplY3QsXG4gIEludmVudG9yeVNlcnZpY2UsXG4gIElPcGVyYXRpb24sXG4gIElSZXN1bHRMaXN0LFxuICBPcGVyYXRpb25TZXJ2aWNlLFxuICBPcGVyYXRpb25TdGF0dXMsXG4gIFF1ZXJpZXNVdGlsXG59IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IEFsZXJ0U2VydmljZSwgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHtcbiAgZ2V0LFxuICBpc0VtcHR5LFxuICBpc05pbCxcbiAga2V5QnksXG4gIGtleXMsXG4gIG1hcFZhbHVlcyxcbiAgb21pdEJ5LFxuICBwaWNrQnksXG4gIHNvcnRCeSxcbiAgdG9BcnJheSxcbiAgdW5pcUJ5XG59IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQge1xuICBDb21wYXJpc29uUmVzdWx0LFxuICBEZXZpY2VQcm9maWxlLFxuICBEZXZpY2VQcm9maWxlRmlybXdhcmUsXG4gIERldmljZVByb2ZpbGVTb2Z0d2FyZVxufSBmcm9tICcuL2RldmljZS1wcm9maWxlLm1vZGVsJztcblxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIERldmljZVByb2ZpbGVTZXJ2aWNlIHtcbiAgcmVhZG9ubHkgZGF0ZUZyb20gPSBuZXcgRGF0ZSgwKTtcbiAgcmVhZG9ubHkgZGF0ZVRvID0gbmV3IERhdGUoRGF0ZS5ub3coKSArIDg2NDAwMDAwKTsgLy8gMSBkYXkgaW4gdGhlIGZ1dHVyZVxuICBwcml2YXRlIHF1ZXJpZXNVdGlsOiBRdWVyaWVzVXRpbDtcblxuICBwcml2YXRlIE5PVF9JTlNUQUxMRURfV0FSTklORyA9IGdldHRleHQoJ05vdCBpbnN0YWxsZWQgb24gdGhlIGRldmljZScpO1xuICBwcml2YXRlIFZFUlNJT05fTUlTU01BVENIX1dBUk5JTkcgPSBnZXR0ZXh0KCdWZXJzaW9uIG1pc21hdGNoJyk7XG4gIHByaXZhdGUgU0FNRV9VUkxfV0FSTklORyA9IGdldHRleHQoXG4gICAgJ0luc3RhbGxlZCBjb25maWd1cmF0aW9uIGhhcyB0aGUgc2FtZSBVUkwgYnV0IGRpZmZlcmVudCBuYW1lIG9yIHR5cGUgdGhhbiB0aGUgb25lIGluIHRoZSBwcm9maWxlJ1xuICApO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgaW52ZW50b3J5U2VydmljZTogSW52ZW50b3J5U2VydmljZSxcbiAgICBwcml2YXRlIG9wZXJhdGlvblNlcnZpY2U6IE9wZXJhdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhbGVydFNlcnZpY2U6IEFsZXJ0U2VydmljZVxuICApIHtcbiAgICB0aGlzLnF1ZXJpZXNVdGlsID0gbmV3IFF1ZXJpZXNVdGlsKCk7XG4gIH1cblxuICBjcmVhdGVEZXZpY2VQcm9maWxlKGRldmljZVByb2ZpbGU6IFBhcnRpYWw8RGV2aWNlUHJvZmlsZT4pIHtcbiAgICBpZiAoZ2V0KGRldmljZVByb2ZpbGUsICdjOHlfRmlsdGVyLnR5cGUnKSA9PT0gJycpIHtcbiAgICAgIGRlbGV0ZSBkZXZpY2VQcm9maWxlLmM4eV9GaWx0ZXIudHlwZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuaW52ZW50b3J5U2VydmljZS5jcmVhdGUoZGV2aWNlUHJvZmlsZSBhcyBJTWFuYWdlZE9iamVjdCk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgYXZhaWxhYmxlIGRldmljZSBwcm9maWxlcyBmb3IgYSBnaXZlbiBkZXZpY2UgYnkgY29uc2lkZXJpbmcgZGV2aWNlIHR5cGVcbiAgICogYW5kIHRoZSBzdXBwb3J0ZWQgc29mdHdhcmUgdHlwZXMgZGVjbGFyZWQgYnkgdGhlIGRldmljZXMuIEJlY2F1c2Ugb2YgbGltaXRhdGlvbnMgaW4gdGhlXG4gICAqIEludmVudG9yeSBRdWVyeSBBUEkgdGhlIG1ldGhvZHMgcmV0dXJuIHByb2ZpbGUgdGhhdCBjb250YWluIGF0IGxlYXN0IG9uZSBvZiB0aGUgc3VwcG9ydGVkXG4gICAqIHNvZnR3YXJlIHR5cGVzIGFuZCBvbWl0cyBwcm9maWxlcyBoYXZpbmcgb25seSBub24tc3VwcG9ydGVkIHNvZnR3YXJlIHR5cGVzLiBSZXN1bHRpbmcgZGV2aWNlXG4gICAqIHByb2ZpbGVzIG5lZWQgdG8gYmUgZnVydGhlciBmaWx0ZXJlZCBvbiB0aGUgY2xpZW50IHNpZGUgdG8gZXhjbHVkZSB0aGUgb25lcyB0aGF0IGNvbnRhaW5cbiAgICogbm9uLXN1cHBvcnRlZCBzb2Z0d2FyZSB0eXBlcyBuZXh0IHRvIHRoZSBzdXBwb3J0ZWQgb25lcy5cbiAgICpcbiAgICogQHBhcmFtIGRldmljZSBBIGRldmljZSBNT1xuICAgKiBAcGFyYW0gbmFtZSBPcHRpb25hbCBkZXZpY2UgcHJvZmlsZSBuYW1lIGZpbHRlclxuICAgKiBAcmV0dXJucyBDYW5kaWRhdGUgZGV2aWNlIHByb2ZpbGVzIHRoYXQgY29udGFpbiBhdCBsZWFzdCBvbiBzb2Z0d2FyZSB3aXRoIHN1cHBvcnRlZCB0eXBlLlxuICAgKi9cbiAgZ2V0RGV2aWNlUHJvZmlsZXNCeURldmljZShcbiAgICBkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LFxuICAgIG5hbWU6IHN0cmluZyA9IG51bGxcbiAgKTogUHJvbWlzZTxJUmVzdWx0TGlzdDxJTWFuYWdlZE9iamVjdD4+IHtcbiAgICBjb25zdCBkZXZpY2VUeXBlRmlsdGVyID0ge1xuICAgICAgX19vcjogW1xuICAgICAgICB7ICdjOHlfRmlsdGVyLnR5cGUnOiBkZXZpY2UudHlwZSB9LFxuICAgICAgICB7ICdjOHlfRmlsdGVyLnR5cGUnOiAnJyB9LFxuICAgICAgICB7IF9fbm90OiB7IF9faGFzOiAnYzh5X0ZpbHRlci50eXBlJyB9IH1cbiAgICAgIF1cbiAgICB9O1xuXG4gICAgbGV0IHNvZnR3YXJlVHlwZUZpbHRlciA9IHt9O1xuICAgIGlmICghaXNFbXB0eShkZXZpY2UuYzh5X1N1cHBvcnRlZFNvZnR3YXJlVHlwZXMpKSB7XG4gICAgICBzb2Z0d2FyZVR5cGVGaWx0ZXIgPSB7XG4gICAgICAgIF9faGFzYW55OiBkZXZpY2UuYzh5X1N1cHBvcnRlZFNvZnR3YXJlVHlwZXMubWFwKCh0eXBlOiBzdHJpbmcpID0+IGBzb2Z0d2FyZVR5cGUhJHt0eXBlfWApXG4gICAgICB9O1xuICAgIH1cbiAgICBsZXQgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihkZXZpY2VUeXBlRmlsdGVyLCBzb2Z0d2FyZVR5cGVGaWx0ZXIpO1xuXG4gICAgbGV0IHByb2ZpbGVOYW1lRmlsdGVyID0ge307XG4gICAgaWYgKCFpc0VtcHR5KG5hbWUpKSB7XG4gICAgICBwcm9maWxlTmFtZUZpbHRlciA9IHsgbmFtZTogYCoke25hbWV9KmAgfTtcbiAgICB9XG4gICAgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihxdWVyeSwgcHJvZmlsZU5hbWVGaWx0ZXIpO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2V0RGV2aWNlUHJvZmlsZXMocXVlcnkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIFVzZSBgZ2V0RGV2aWNlUHJvZmlsZXNCeURldmljZWAgaW5zdGVhZCBhcyBpdCBhbHNvIGNvbnNpZGVycyB0aGUgc3VwcG9ydGVkIHNvZnR3YXJlIHR5cGVzLlxuICAgKi9cbiAgZ2V0RGV2aWNlUHJvZmlsZXNCeURldmljZVR5cGUoZGV2aWNlVHlwZTogc3RyaW5nKTogUHJvbWlzZTxJUmVzdWx0TGlzdDxJTWFuYWdlZE9iamVjdD4+IHtcbiAgICBjb25zdCBkZXZpY2VUeXBlRmlsdGVyID0ge1xuICAgICAgX19vcjogW1xuICAgICAgICB7ICdjOHlfRmlsdGVyLnR5cGUnOiBkZXZpY2VUeXBlIH0sXG4gICAgICAgIHsgJ2M4eV9GaWx0ZXIudHlwZSc6ICcnIH0sXG4gICAgICAgIHsgX19ub3Q6IHsgX19oYXM6ICdjOHlfRmlsdGVyLnR5cGUnIH0gfVxuICAgICAgXVxuICAgIH07XG4gICAgcmV0dXJuIHRoaXMuZ2V0RGV2aWNlUHJvZmlsZXMoZGV2aWNlVHlwZUZpbHRlcik7XG4gIH1cblxuICBnZXREZXZpY2VQcm9maWxlcyhhbmRRdWVyeT86IGFueSk6IFByb21pc2U8SVJlc3VsdExpc3Q8SU1hbmFnZWRPYmplY3Q+PiB7XG4gICAgbGV0IHF1ZXJ5OiBvYmplY3QgPSB7XG4gICAgICB0eXBlOiAnYzh5X1Byb2ZpbGUnXG4gICAgfTtcbiAgICBjb25zdCBmaWx0ZXI6IG9iamVjdCA9IHtcbiAgICAgIHBhZ2VTaXplOiAxMDAsXG4gICAgICB3aXRoVG90YWxQYWdlczogdHJ1ZVxuICAgIH07XG4gICAgcXVlcnkgPSB0aGlzLnF1ZXJpZXNVdGlsLmFkZEFuZEZpbHRlcihxdWVyeSwgYW5kUXVlcnkgfHwge30pO1xuICAgIHJldHVybiB0aGlzLmludmVudG9yeVNlcnZpY2UubGlzdFF1ZXJ5KHF1ZXJ5LCBmaWx0ZXIpO1xuICB9XG5cbiAgYXN5bmMgZ2V0UHJvZmlsZU9wZXJhdGlvbihkZXZpY2VJZDogc3RyaW5nIHwgbnVtYmVyKSB7XG4gICAgY29uc3QgZmlsdGVyOiBvYmplY3QgPSB7XG4gICAgICBkZXZpY2VJZCxcbiAgICAgIGZyYWdtZW50VHlwZTogJ2M4eV9EZXZpY2VQcm9maWxlJyxcbiAgICAgIGRhdGVGcm9tOiB0aGlzLmRhdGVGcm9tLnRvSVNPU3RyaW5nKCksXG4gICAgICBkYXRlVG86IHRoaXMuZGF0ZVRvLnRvSVNPU3RyaW5nKCksXG4gICAgICByZXZlcnQ6IHRydWUsXG4gICAgICBwYWdlU2l6ZTogMVxuICAgIH07XG5cbiAgICBjb25zdCBvcGVyYXRpb24gPSAoYXdhaXQgdGhpcy5vcGVyYXRpb25TZXJ2aWNlLmxpc3QoZmlsdGVyKSkuZGF0YVswXTtcbiAgICByZXR1cm4gb3BlcmF0aW9uICYmIG9wZXJhdGlvbi5zdGF0dXMgIT09IE9wZXJhdGlvblN0YXR1cy5TVUNDRVNTRlVMID8gb3BlcmF0aW9uIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgYXN5bmMgY3JlYXRlUHJvZmlsZU9wZXJhdGlvbihkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LCBkZXZpY2VQcm9maWxlOiBQYXJ0aWFsPERldmljZVByb2ZpbGU+KSB7XG4gICAgbGV0IG9wZXJhdGlvbjtcbiAgICBjb25zdCBvcGVyYXRpb25DZmc6IElPcGVyYXRpb24gPSB7XG4gICAgICBkZXZpY2VJZDogZGV2aWNlLmlkLFxuICAgICAgcHJvZmlsZUlkOiBkZXZpY2VQcm9maWxlLmlkLFxuICAgICAgcHJvZmlsZU5hbWU6IGRldmljZVByb2ZpbGUubmFtZSxcbiAgICAgIGM4eV9EZXZpY2VQcm9maWxlOiBkZXZpY2VQcm9maWxlLmM4eV9EZXZpY2VQcm9maWxlLFxuICAgICAgZGVzY3JpcHRpb246IGBBc3NpZ24gZGV2aWNlIHByb2ZpbGUgJHtkZXZpY2VQcm9maWxlLm5hbWV9IHRvIGRldmljZSAke2RldmljZS5uYW1lfWBcbiAgICB9O1xuICAgIHRyeSB7XG4gICAgICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IHRoaXMub3BlcmF0aW9uU2VydmljZS5jcmVhdGUob3BlcmF0aW9uQ2ZnKTtcbiAgICAgIG9wZXJhdGlvbiA9IGRhdGE7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmFkZFNlcnZlckZhaWx1cmUoZXgpO1xuICAgIH1cbiAgICByZXR1cm4gb3BlcmF0aW9uO1xuICB9XG5cbiAgZ2V0RmlybXdhcmVJdGVtcyhcbiAgICBkZXZpY2U6IElNYW5hZ2VkT2JqZWN0LFxuICAgIHNlbGVjdGVkUHJvZmlsZTogUGFydGlhbDxEZXZpY2VQcm9maWxlPlxuICApOiBDb21wYXJpc29uUmVzdWx0W10ge1xuICAgIGNvbnN0IGRldmljZUZpcm13YXJlID0gZGV2aWNlLmM4eV9GaXJtd2FyZTtcbiAgICBjb25zdCBwcm9maWxlRmlybXdhcmUgPSBnZXQoc2VsZWN0ZWRQcm9maWxlLCAnYzh5X0RldmljZVByb2ZpbGUuZmlybXdhcmUnKTtcbiAgICBjb25zdCBkZXZpY2VJdGVtcyA9IFtdO1xuICAgIGNvbnN0IHByb2ZpbGVJdGVtcyA9IFtdO1xuXG4gICAgaWYgKGRldmljZUZpcm13YXJlKSB7XG4gICAgICBkZXZpY2VJdGVtcy5wdXNoKGRldmljZUZpcm13YXJlKTtcbiAgICB9XG4gICAgaWYgKHByb2ZpbGVGaXJtd2FyZSkge1xuICAgICAgcHJvZmlsZUl0ZW1zLnB1c2gocHJvZmlsZUZpcm13YXJlKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlUHJvZmlsZUNvbXBhcmlzb24oXG4gICAgICBkZXZpY2VJdGVtcyxcbiAgICAgIHByb2ZpbGVJdGVtcyxcbiAgICAgICduYW1lJyxcbiAgICAgICd2ZXJzaW9uJyxcbiAgICAgIG51bGwsXG4gICAgICB0aGlzLmdldEFsZXJ0KCdmaXJtd2FyZScpXG4gICAgKTtcbiAgfVxuXG4gIGdldFNvZnR3YXJlSXRlbXMoXG4gICAgZGV2aWNlOiBJTWFuYWdlZE9iamVjdCxcbiAgICBzZWxlY3RlZFByb2ZpbGU6IFBhcnRpYWw8RGV2aWNlUHJvZmlsZT5cbiAgKTogQ29tcGFyaXNvblJlc3VsdFtdIHtcbiAgICBjb25zdCBkZXZpY2VTb2Z0d2FyZSA9IGRldmljZS5jOHlfU29mdHdhcmVMaXN0O1xuICAgIGNvbnN0IHByb2ZpbGVTb2Z0d2FyZSA9IGdldChzZWxlY3RlZFByb2ZpbGUsICdjOHlfRGV2aWNlUHJvZmlsZS5zb2Z0d2FyZScpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVByb2ZpbGVDb21wYXJpc29uKFxuICAgICAgZGV2aWNlU29mdHdhcmUsXG4gICAgICBwcm9maWxlU29mdHdhcmUsXG4gICAgICAnbmFtZScsXG4gICAgICAndmVyc2lvbicsXG4gICAgICAnc29mdHdhcmVUeXBlJyxcbiAgICAgIHRoaXMuZ2V0QWxlcnQoJ3NvZnR3YXJlJylcbiAgICApO1xuICB9XG5cbiAgZ2V0Q29uZmlndXJhdGlvbkl0ZW1zKFxuICAgIGRldmljZTogSU1hbmFnZWRPYmplY3QsXG4gICAgc2VsZWN0ZWRQcm9maWxlOiBQYXJ0aWFsPERldmljZVByb2ZpbGU+XG4gICk6IENvbXBhcmlzb25SZXN1bHRbXSB7XG4gICAgY29uc3QgZGV2aWNlQ29uZmlndXJhdGlvbiA9IFtdO1xuICAgIE9iamVjdC5rZXlzKGRldmljZSkuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgaWYgKGtleS5zbGljZSgwLCAxOCkgPT09ICdjOHlfQ29uZmlndXJhdGlvbl8nKSB7XG4gICAgICAgIGRldmljZUNvbmZpZ3VyYXRpb24ucHVzaChkZXZpY2Vba2V5XSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgY29uc3QgcHJvZmlsZUNvbmZpZ3VyYXRpb24gPSBnZXQoc2VsZWN0ZWRQcm9maWxlLCAnYzh5X0RldmljZVByb2ZpbGUuY29uZmlndXJhdGlvbicpO1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVByb2ZpbGVDb21wYXJpc29uKFxuICAgICAgZGV2aWNlQ29uZmlndXJhdGlvbixcbiAgICAgIHByb2ZpbGVDb25maWd1cmF0aW9uLFxuICAgICAgJ3VybCcsXG4gICAgICBudWxsLFxuICAgICAgJ3R5cGUnLFxuICAgICAgdGhpcy5nZXRBbGVydCgnY29uZmlndXJhdGlvbicpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGlnbnMgZGV2aWNlIHByb2ZpbGUgbWFuYWdlZCBvYmplY3QncyBgc29mdHdhcmVUeXBlISpgIGZyYWdtZW50cyB0byB0aGUgc29mdHdhcmUgaXRlbXNcbiAgICogaW5jbHVkZWQgaW4gdGhlIGRldmljZSBwcm9maWxlLiBSZW1vdmVzIG9ic29sZXRlIHNvZnR3YXJlIHR5cGUgZnJhZ21lbnRzIGFuZCBhZGRzIG5ldy5cbiAgICpcbiAgICogQHBhcmFtIHByb2ZpbGVQYXJ0aWFsIFRoZSBkZXZpY2UgcHJvZmlsZSBtYW5hZ2VkIG9iamVjdCB3aGljaCBgc29mdHdhcmVUeXBlISpgIGZyYWdtZW50cyB3aWxsIGJlIGFkanVzdGVkLlxuICAgKiBAcmV0dXJucyBUaGUgYWRqdXN0ZWQgZGV2aWNlIHByb2ZpbGUgbWFuYWdlZCBvYmplY3QuXG4gICAqL1xuICBhbGlnblNvZnR3YXJlVHlwZUZyYWdtZW50cyhcbiAgICBwcm9maWxlUGFydGlhbDogUGFydGlhbDxEZXZpY2VQcm9maWxlPixcbiAgICBwcm9maWxlOiBEZXZpY2VQcm9maWxlXG4gICk6IFBhcnRpYWw8RGV2aWNlUHJvZmlsZT4ge1xuICAgIGlmICghcHJvZmlsZVBhcnRpYWw/LmM4eV9EZXZpY2VQcm9maWxlPy5zb2Z0d2FyZSB8fCAhcHJvZmlsZSkge1xuICAgICAgcmV0dXJuIHByb2ZpbGVQYXJ0aWFsO1xuICAgIH1cblxuICAgIGNvbnN0IHJlbW92ZWRTb2Z0d2FyZVR5cGVzID0gbWFwVmFsdWVzKFxuICAgICAgb21pdEJ5KFxuICAgICAgICBwcm9maWxlLFxuICAgICAgICAoXzogdW5rbm93biwga2V5OiBQcm9wZXJ0eUtleSkgPT5cbiAgICAgICAgICB0eXBlb2Yga2V5ID09PSAnc3RyaW5nJyAmJiAha2V5LnN0YXJ0c1dpdGgoJ3NvZnR3YXJlVHlwZSEnKVxuICAgICAgKSxcbiAgICAgICgpID0+IG51bGxcbiAgICApO1xuICAgIGNvbnN0IHNvZnR3YXJlVHlwZXNUb0FkZDogeyBba2V5OiBQcm9wZXJ0eUtleV06IFJlY29yZDxQcm9wZXJ0eUtleSwgbmV2ZXI+IH0gPSBtYXBWYWx1ZXMoXG4gICAgICBrZXlCeShcbiAgICAgICAgdW5pcUJ5KHByb2ZpbGVQYXJ0aWFsLmM4eV9EZXZpY2VQcm9maWxlLnNvZnR3YXJlLCAnc29mdHdhcmVUeXBlJyksXG4gICAgICAgIChwcm9maWxlOiBEZXZpY2VQcm9maWxlU29mdHdhcmUpID0+IGBzb2Z0d2FyZVR5cGUhJHtwcm9maWxlLnNvZnR3YXJlVHlwZX1gXG4gICAgICApLFxuICAgICAgKCkgPT4gKHt9KVxuICAgICk7XG5cbiAgICBjb25zdCByZXN1bHQgPSB7IC4uLnByb2ZpbGVQYXJ0aWFsLCAuLi5yZW1vdmVkU29mdHdhcmVUeXBlcywgLi4uc29mdHdhcmVUeXBlc1RvQWRkIH07XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGdldFNvZnR3YXJlVHlwZXMocHJvZmlsZTogRGV2aWNlUHJvZmlsZSk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4ga2V5cyhcbiAgICAgIHBpY2tCeShcbiAgICAgICAgcHJvZmlsZSxcbiAgICAgICAgKF86IHVua25vd24sIGtleTogUHJvcGVydHlLZXkpID0+IHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnICYmIGtleS5zdGFydHNXaXRoKCdzb2Z0d2FyZVR5cGUhJylcbiAgICAgIClcbiAgICApLm1hcChzb2Z0d2FyZVR5cGUgPT4gc29mdHdhcmVUeXBlLnN1YnN0cignc29mdHdhcmVUeXBlIScubGVuZ3RoKSk7XG4gIH1cblxuICBwcml2YXRlIGdldEFsZXJ0KGl0ZW1UeXBlOiBzdHJpbmcpOiAoY29tcGFyaXNpb25SZXN1bHQ6IENvbXBhcmlzb25SZXN1bHQpID0+IHN0cmluZyB7XG4gICAgY29uc3Qgbm90SW5zdGFsbGVkID0gKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiB7XG4gICAgICByZXR1cm4gIWNvbXBhcmlzaW9uUmVzdWx0LmRldmljZSA/IHRoaXMuTk9UX0lOU1RBTExFRF9XQVJOSU5HIDogJyc7XG4gICAgfTtcblxuICAgIHN3aXRjaCAoaXRlbVR5cGUpIHtcbiAgICAgIGNhc2UgJ2Zpcm13YXJlJzpcbiAgICAgIGNhc2UgJ3NvZnR3YXJlJzpcbiAgICAgICAgcmV0dXJuIChjb21wYXJpc2lvblJlc3VsdDogQ29tcGFyaXNvblJlc3VsdCkgPT4ge1xuICAgICAgICAgIHJldHVybiBjb21wYXJpc2lvblJlc3VsdC5kZXZpY2UgJiZcbiAgICAgICAgICAgIGNvbXBhcmlzaW9uUmVzdWx0LnByb2ZpbGUgJiZcbiAgICAgICAgICAgIGNvbXBhcmlzaW9uUmVzdWx0LmRldmljZS5pdGVtRGV0YWlscyAhPT0gY29tcGFyaXNpb25SZXN1bHQucHJvZmlsZS5pdGVtRGV0YWlsc1xuICAgICAgICAgICAgPyB0aGlzLlZFUlNJT05fTUlTU01BVENIX1dBUk5JTkdcbiAgICAgICAgICAgIDogbm90SW5zdGFsbGVkKGNvbXBhcmlzaW9uUmVzdWx0KTtcbiAgICAgICAgfTtcbiAgICAgIGNhc2UgJ2NvbmZpZ3VyYXRpb24nOlxuICAgICAgICByZXR1cm4gKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGNvbXBhcmlzaW9uUmVzdWx0LmRldmljZSAmJlxuICAgICAgICAgICAgY29tcGFyaXNpb25SZXN1bHQucHJvZmlsZSAmJlxuICAgICAgICAgICAgKGNvbXBhcmlzaW9uUmVzdWx0LmRldmljZS5pdGVtTmFtZSAhPT0gY29tcGFyaXNpb25SZXN1bHQucHJvZmlsZS5pdGVtTmFtZSB8fFxuICAgICAgICAgICAgICBjb21wYXJpc2lvblJlc3VsdC5kZXZpY2UuaXRlbURldGFpbHMgIT09IGNvbXBhcmlzaW9uUmVzdWx0LnByb2ZpbGUuaXRlbURldGFpbHMpXG4gICAgICAgICAgICA/IHRoaXMuU0FNRV9VUkxfV0FSTklOR1xuICAgICAgICAgICAgOiBub3RJbnN0YWxsZWQoY29tcGFyaXNpb25SZXN1bHQpO1xuICAgICAgICB9O1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIG5vdEluc3RhbGxlZDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNyZWF0ZVByb2ZpbGVDb21wYXJpc29uKFxuICAgIGRldmljZUl0ZW1zOiBhbnlbXSA9IFtdLFxuICAgIHByb2ZpbGVJdGVtczogQXJyYXk8RGV2aWNlUHJvZmlsZVNvZnR3YXJlIHwgRGV2aWNlUHJvZmlsZUZpcm13YXJlPiA9IFtdLFxuICAgIG1lcmdlQnlQcm9wZXJ0eTogc3RyaW5nLFxuICAgIHByb3BlcnR5TmFtZVdpdGhEZXRhaWxzOiBzdHJpbmcsXG4gICAgcHJvcGVydHlOYW1lV2l0aFR5cGU6IHN0cmluZyxcbiAgICBnZXRBbGVydDogKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiBzdHJpbmdcbiAgKTogQ29tcGFyaXNvblJlc3VsdFtdIHtcbiAgICBjb25zdCBjb21wYXJpc29uT2JqID0gdGhpcy5jcmVhdGVQcm9maWxlQ29tcGFyaXNvbkZyb21EZXZpY2VJdGVtcyhcbiAgICAgIGRldmljZUl0ZW1zLFxuICAgICAgbWVyZ2VCeVByb3BlcnR5LFxuICAgICAgcHJvcGVydHlOYW1lV2l0aERldGFpbHMsXG4gICAgICBwcm9wZXJ0eU5hbWVXaXRoVHlwZVxuICAgICk7XG4gICAgY29uc3QgZXh0ZW5kZWRDb21wYXJpc29uT2JqID0gdGhpcy5leHRlbmRQcm9maWxlQ29tcGFyaXNvbldpdGhQcm9maWxlSXRlbXMoXG4gICAgICBjb21wYXJpc29uT2JqLFxuICAgICAgcHJvZmlsZUl0ZW1zLFxuICAgICAgbWVyZ2VCeVByb3BlcnR5LFxuICAgICAgcHJvcGVydHlOYW1lV2l0aERldGFpbHMsXG4gICAgICBwcm9wZXJ0eU5hbWVXaXRoVHlwZSxcbiAgICAgIGdldEFsZXJ0XG4gICAgKTtcbiAgICByZXR1cm4gc29ydEJ5KHRvQXJyYXkoZXh0ZW5kZWRDb21wYXJpc29uT2JqKSwgJ25hbWUnKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUHJvZmlsZUNvbXBhcmlzb25Gcm9tRGV2aWNlSXRlbXMoXG4gICAgZGV2aWNlSXRlbXM6IGFueVtdLFxuICAgIG1lcmdlQnlQcm9wZXJ0eTogc3RyaW5nLFxuICAgIHByb3BlcnR5TmFtZVdpdGhEZXRhaWxzOiBzdHJpbmcsXG4gICAgcHJvcGVydHlOYW1lV2l0aFR5cGU6IHN0cmluZ1xuICApOiBhbnkge1xuICAgIHJldHVybiBkZXZpY2VJdGVtcy5yZWR1Y2UoXG4gICAgICAoY29tYXByaXRpb25JdGVtLCBkZXZpY2VJdGVtKSA9PlxuICAgICAgICBPYmplY3QuYXNzaWduKGNvbWFwcml0aW9uSXRlbSwge1xuICAgICAgICAgIFtkZXZpY2VJdGVtW21lcmdlQnlQcm9wZXJ0eV1dOiB7XG4gICAgICAgICAgICBkZXZpY2U6IG9taXRCeShcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGl0ZW1OYW1lOiBkZXZpY2VJdGVtLm5hbWUsXG4gICAgICAgICAgICAgICAgaXRlbURldGFpbHM6IGRldmljZUl0ZW1bcHJvcGVydHlOYW1lV2l0aERldGFpbHNdLFxuICAgICAgICAgICAgICAgIGl0ZW1UeXBlOiBkZXZpY2VJdGVtW3Byb3BlcnR5TmFtZVdpdGhUeXBlXSxcbiAgICAgICAgICAgICAgICBpdGVtVXJsOiBkZXZpY2VJdGVtLnVybFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICBpc05pbFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHByb2ZpbGU6IHVuZGVmaW5lZFxuICAgICAgICAgIH1cbiAgICAgICAgfSksXG4gICAgICB7fVxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIGV4dGVuZFByb2ZpbGVDb21wYXJpc29uV2l0aFByb2ZpbGVJdGVtcyhcbiAgICBjb21wYXJpc29uT2JqOiBvYmplY3QsXG4gICAgcHJvZmlsZUl0ZW1zOiBBcnJheTxEZXZpY2VQcm9maWxlU29mdHdhcmUgfCBEZXZpY2VQcm9maWxlRmlybXdhcmU+LFxuICAgIG1lcmdlQnlQcm9wZXJ0eTogc3RyaW5nLFxuICAgIHByb3BlcnR5TmFtZVdpdGhEZXRhaWxzOiBzdHJpbmcsXG4gICAgcHJvcGVydHlOYW1lV2l0aFR5cGU6IHN0cmluZyxcbiAgICBnZXRBbGVydDogKGNvbXBhcmlzaW9uUmVzdWx0OiBDb21wYXJpc29uUmVzdWx0KSA9PiBzdHJpbmdcbiAgKSB7XG4gICAgcHJvZmlsZUl0ZW1zLmZvckVhY2gocHJvZmlsZUl0ZW0gPT4ge1xuICAgICAgY29uc3QgY29tcGFyaXNpb25SZXN1bHQ6IENvbXBhcmlzb25SZXN1bHQgPSB7XG4gICAgICAgIHByb2ZpbGU6IG9taXRCeShcbiAgICAgICAgICB7XG4gICAgICAgICAgICBpdGVtTmFtZTogcHJvZmlsZUl0ZW0ubmFtZSxcbiAgICAgICAgICAgIGl0ZW1EZXRhaWxzOiBwcm9maWxlSXRlbVtwcm9wZXJ0eU5hbWVXaXRoRGV0YWlsc10sXG4gICAgICAgICAgICBpdGVtVHlwZTogcHJvZmlsZUl0ZW1bcHJvcGVydHlOYW1lV2l0aFR5cGVdLFxuICAgICAgICAgICAgaXRlbVVybDogcHJvZmlsZUl0ZW0udXJsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBpc05pbFxuICAgICAgICApLFxuICAgICAgICBkZXZpY2U6IGNvbXBhcmlzb25PYmpbcHJvZmlsZUl0ZW1bbWVyZ2VCeVByb3BlcnR5XV1cbiAgICAgICAgICA/IGNvbXBhcmlzb25PYmpbcHJvZmlsZUl0ZW1bbWVyZ2VCeVByb3BlcnR5XV0uZGV2aWNlXG4gICAgICAgICAgOiB1bmRlZmluZWRcbiAgICAgIH07XG4gICAgICBjb21wYXJpc2lvblJlc3VsdC5jb21wYXJpc29uQWxlcnQgPSBnZXRBbGVydChjb21wYXJpc2lvblJlc3VsdCk7XG4gICAgICBjb21wYXJpc29uT2JqW3Byb2ZpbGVJdGVtW21lcmdlQnlQcm9wZXJ0eV1dID0gY29tcGFyaXNpb25SZXN1bHQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvbXBhcmlzb25PYmo7XG4gIH1cbn1cbiJdfQ==