Untitled
unknown
plain_text
2 years ago
42 kB
10
Indexable
import { AfterViewInit, Component, ElementRef, OnInit, ViewChild, } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import * as moment from 'moment'; import { ExternalReadtimeseriesService } from 'src/app/api/services'; import { dashboardsDetails } from 'src/app/constants/dashboard'; import { AxisType, ChartConfiguration, ChartData, DateRangePickerConfiguration, FormControlConfiguration, FormSelectOption, intervalType, LegendPosition, LineTypeCrossHair, ModeTypeZoom, PaginatorConfiguration, ShapeLegend, TabConfiguration, TabGroupConfiguration, TableConfiguration, TypeChart, } from 'widgets'; import { ChartService } from 'src/app/services/chart.service'; import { DashboardDetailDto } from 'src/app/models/dashboard/dashboard-detail-dto'; import { catchError, forkJoin, of } from 'rxjs'; import { TelemetryStruct } from 'src/app/models/dashboard/telemetry_struct'; import { TranslateService } from '@ngx-translate/core'; import { MatAccordion } from '@angular/material/expansion'; import { FormControl, FormGroup, Validators } from '@angular/forms'; import { formsInputConfiguration, formsName, } from 'src/app/constants/formConfiguration'; import { FormService } from 'src/app/services/utilities/form/form.service'; import { DeviceForTelemetry } from 'src/app/models/dashboard/device-for-telemetry'; import { TableService } from 'src/app/services/utilities/table/table.service'; import { tableConfigurationName } from 'src/app/constants/tableConfiguration'; import { TsValuePair } from 'src/app/api/models'; @Component({ selector: 'app-dashboard-detail', templateUrl: './dashboard-detail.component.html', styleUrls: ['./dashboard-detail.component.scss'], }) export class DashboardDetailComponent implements OnInit, AfterViewInit { Object = Object; moment = moment; loadingData = false; //dashboard and charts dashboard?: DashboardDetailDto; _chartsData?: Map< string, | { chartConfiguration?: ChartConfiguration; telemetries?: ChartData; telemetryKeys?: string[]; allDeviceNames?: string[]; form?: FormGroup; formInputs?: FormControlConfiguration[]; predictiveForm?: FormGroup; predictiveFormInputs?: FormControlConfiguration[]; expanded?: boolean; currentTableDevice?: DeviceForTelemetry; tableData?: { devices: { data: { telemetryTs?: number; telemetryValue?: number; anomalyValue?: number; predicitedTelemetryValue?: number; predicitedFutureTelemetryValue?: number; }[]; currentPageData: { telemetryTs?: number; telemetryValue?: number; anomalyValue?: number; predicitedTelemetryValue?: number; predicitedFutureTelemetryValue?: number; }[]; device: DeviceForTelemetry; pageNumber: number; pageSize: number; totalNumber: number; configurationPaginator: PaginatorConfiguration; }[]; form: FormGroup; formInputs: FormControlConfiguration[]; unit: string; configurationTabGroup: TabGroupConfiguration; }; } | undefined >; configurationTable!: TableConfiguration; configurationPaginator!: PaginatorConfiguration; configurationTabGroup: TabGroupConfiguration = { configuration: [] }; tableDataMap?: Map< string, { devices: { data: { telemetryTs?: number; telemetryValue?: number; anomalyValue?: number; }[]; currentPageData: { telemetryTs?: number; telemetryValue?: number; anomalyValue?: number; }[]; device: DeviceForTelemetry; pageNumber: number; pageSize: number; totalNumber: number; configurationPaginator: PaginatorConfiguration; }[]; form: FormGroup; formInputs: FormControlConfiguration[]; unit: string; configurationTabGroup: TabGroupConfiguration; } >; get chartsData() { return this._chartsData; } set chartsData(value) { this.loadingData = false; this._chartsData = value; } get telemetryKeyList(): string[] { return this.telemetriesList.map((e) => e.value); } //// accordion @ViewChild(MatAccordion) accordion!: MatAccordion; /// multiselect telemetriesList: FormSelectOption[] = []; ficTL!: FormControlConfiguration[]; formTL!: FormGroup; showSelection: string[] = []; //// date rangeSelected: { startDate: Date; endDate: Date } = { startDate: new Date(), endDate: new Date(), }; aggregationInterval?: any; dateControl = new FormControl(null); @ViewChild('datePickerRange') dateRangePicker?: any; get dateRangePickerConfiguration(): DateRangePickerConfiguration { return { placeholder: 'Seleziona un range', format: 'dd/MM/yyyy HH:mm', control: this.dateControl, locale: 'it', ranges: [ { label: 'Ultime 24h', start: new Date( new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), new Date().getHours() - 24, new Date().getMinutes() ), end: new Date(), }, { label: 'Ultima settimana', start: new Date( new Date().getFullYear(), new Date().getMonth(), new Date().getDate() - new Date().getDay() - 6, new Date().getHours(), new Date().getMinutes() ), end: new Date(), }, { label: 'Ultimo Mese', start: new Date(new Date().setMonth(new Date().getMonth() - 1)), end: new Date(), }, { label: 'Ultimo Anno', start: new Date(new Date().setMonth(new Date().getMonth() - 12)), end: new Date(), }, ], }; } get inputDateRangePicker(): HTMLInputElement | null { return this.elementRef.nativeElement.getElementsByClassName( 'e-input e-lib e-keyboard' ) && this.elementRef.nativeElement.getElementsByClassName( 'e-input e-lib e-keyboard' ).length ? this.elementRef.nativeElement.getElementsByClassName( 'e-input e-lib e-keyboard' )[0] : null; } get openedTelemetryKeys(): string[] { const keys: string[] = []; this.chartsData?.forEach((value, key) => { if (value?.expanded) { keys.push(key); } }); return keys; } get anomalyTelemetryMap() { if (this.chartsData) { const temp = new Map(this.chartsData); Array.from(temp.keys()).forEach((key) => { if (!key.includes('anomaly')) temp.delete(key); }); return temp; } else return undefined; } get predictableTelemetryKeys(): string[] { const predictableTelemetryKeys: string[] = []; if (this.dashboard && this.dashboard.telemetry_device) { this.dashboard.telemetry_device.forEach((telemetryInfo) => { if ( telemetryInfo && telemetryInfo.telemetry && telemetryInfo.telemetry.name.includes('predicted') ) { const splittedByUnderscore = telemetryInfo.telemetry.name.split('_'); const telemetryNameParts = splittedByUnderscore.filter( (val, index) => ![ 'predicted', 'avg', 'f3600s', 'f60s', 'ARIMA', 'LSTM', 'prev', 'future', '60min', '10min', ].includes(val) ); let telemetryKey = ''; telemetryNameParts.forEach((val, index) => { if (index === 0) { telemetryKey += val; } else { telemetryKey += '_' + val; } }); if (!predictableTelemetryKeys.find((key) => key === telemetryKey)) { predictableTelemetryKeys.push(telemetryKey); } } }); } return predictableTelemetryKeys; } constructor( private route: ActivatedRoute, private router: Router, private readTelemetryService: ExternalReadtimeseriesService, private chartService: ChartService, private translateService: TranslateService, private formService: FormService, private elementRef: ElementRef, private tableService: TableService ) { const dashboardId = this.route.snapshot.paramMap.get('id'); if (dashboardId) { // MOCK const dashboard = dashboardsDetails.find( (dashbaord) => dashbaord.id.toString() === dashboardId ); if (dashboard) this.dashboard = dashboard; } const tableConfiguration = this.tableService.buildTable( tableConfigurationName.ANOMALY_DASHBOARD ); this.configurationTable = tableConfiguration.configurationTable; this.configurationPaginator = tableConfiguration.configurationPaginator; } ngOnInit(): void { this.getChartsData(); } //// CHART CONF getChartsData() { const telemetryMap: any = {}; if ( this.dashboard && this.dashboard.telemetry_device && this.dashboard.telemetry_device.length ) { this.loadingData = true; this.dashboard.telemetry_device.forEach((telemetryDevice) => { telemetryMap[telemetryDevice.telemetry!.name!] = { expanded: false, formInputs: JSON.parse( JSON.stringify( this.isTelemetryPredictable(telemetryDevice.telemetry!.name!) ? formsInputConfiguration[formsName.DASHBOARD_FILTERS_FORM] : formsInputConfiguration[ formsName.DASHBOARD_FILTERS_FORM_NO_PREDICTABLE ] ) ), predictiveFormInputs: JSON.parse( JSON.stringify( formsInputConfiguration[ formsName.DASHBOARD_PREDICTIVE_FILTERS_FORM ] ) ), chartConfiguration: this.getChartConfiguration( telemetryDevice.telemetry! ), telemetryKeys: telemetryDevice.devices?.map((dev) => dev.name), allDeviceNames: telemetryDevice.devices?.map((dev) => dev.name), telemetries: {}, }; }); Object.keys(telemetryMap).forEach((key) => { telemetryMap[key]['form'] = this.formService.buildForm( telemetryMap[key]['formInputs'] ); telemetryMap[key]['predictiveForm'] = this.formService.buildForm( telemetryMap[key]['predictiveFormInputs'] ); const options = telemetryMap[key]['predictiveFormInputs'].find( (input: FormControlConfiguration) => input.name === 'predictiveTimeValue' )?.options; const optionToDisable = options.find( (option: FormSelectOption) => option.value === 'prev_10min' ); if (optionToDisable) optionToDisable.disabled = true; telemetryMap[key]['form'] .get('predicted') ?.valueChanges.subscribe((val: boolean) => { if (val) { // TODO: ottimizzare codice ripetuto predictiveinfo const predictiveInfo: { predictiveCaptureInterval: string; predictiveModel: string; predictiveTimeValue: string; } = telemetryMap[key]['predictiveForm'].value; let predictedTelemetry = `predicted_avg_${predictiveInfo.predictiveCaptureInterval}_${key}_${predictiveInfo.predictiveModel}`; if (predictiveInfo.predictiveTimeValue !== 'present') { predictedTelemetry += `_${predictiveInfo.predictiveTimeValue}`; } this.getTelemetriesDataByTelemetryKey(key, predictedTelemetry); } else { const tempTelemetries = { ...this.chartsData!.get(key)?.telemetries, }; this.chartsData!.set(key, { ...this.chartsData!.get(key), telemetryKeys: this.chartsData!.get(key)?.telemetryKeys?.filter( (tempKey: string) => !tempKey.includes('predicted') ), telemetries: {}, }); this.getChartDataByTelemetryKey(key, val); } }); // resetto terzo input quando cambia il secondo e disabilito opzione non possibile telemetryMap[key]['predictiveForm'].controls[ 'predictiveCaptureInterval' ].valueChanges.subscribe((val: any) => { if (val) { const options = telemetryMap[key]['predictiveFormInputs'].find( (input: FormControlConfiguration) => input.name === 'predictiveTimeValue' )?.options; if (options) { if (val === 'f60s') { const optionToDisable = options.find( (option: FormSelectOption) => option.value === 'prev_60min' ); const option = options.find( (option: FormSelectOption) => option.value === 'prev_10min' ); if ( telemetryMap[key]['predictiveForm'].controls[ 'predictiveTimeValue' ].value === 'prev_60min' ) { telemetryMap[key]['predictiveForm'].controls[ 'predictiveTimeValue' ].setValue('prev_10min'); } if (optionToDisable) optionToDisable.disabled = true; if (option) option.disabled = false; } else if (val === 'f3600s') { const optionToDisable = options.find( (option: FormSelectOption) => option.value === 'prev_10min' ); const option = options.find( (option: FormSelectOption) => option.value === 'prev_60min' ); if ( telemetryMap[key]['predictiveForm'].controls[ 'predictiveTimeValue' ].value === 'prev_10min' ) { telemetryMap[key]['predictiveForm'].controls[ 'predictiveTimeValue' ].setValue('prev_60min'); } if (optionToDisable) optionToDisable.disabled = true; if (option) option.disabled = false; } } } }); telemetryMap[key]['predictiveForm']?.valueChanges.subscribe( (val: any) => { this.getTelemetriesDataByTelemetryKey( key, this.getPredictedTelemetryByKey(key), true ); } ); const telemetryInfo = this.dashboard?.telemetry_device?.find( (elem) => elem.telemetry?.name === key ); if (telemetryInfo && telemetryInfo.telemetry && telemetryInfo.devices) { const deviceInput = telemetryMap[key]['formInputs'].find( (input: any) => input.name === 'device' ); if (deviceInput) { deviceInput.options = telemetryInfo.devices.map((device) => { return { value: device.uuid, translate: device.name, tooltip: device.description, }; }); // set default value const defaultVal = [...deviceInput.options]; defaultVal.length >= deviceInput.maxLength ? telemetryMap[key]['form'] .get(deviceInput.name) .setValue( defaultVal.filter( (option, index) => index < deviceInput.maxLength ) ) : telemetryMap[key]['form'] .get(deviceInput.name) .setValue(defaultVal); telemetryMap[key]['telemetryKeys'] = defaultVal.map( (value) => value.translate ); // Quando si cambia insieme di device triggera nuova chiamata per il grafico telemetryMap[key]['form'] .get(deviceInput.name) .valueChanges.subscribe((val: any) => { this.chartsData!.set(key, { ...this.chartsData!.get(key), telemetryKeys: val.map((elem: any) => elem.translate), telemetries: {}, }); this.getChartDataByTelemetryKey( key, this.chartsData!.get(key)?.form?.get('predicted')?.value ); }); deviceInput.compareWithFunc = (a: any, b: any) => { // funzione di comparazione valore settato programmmaticamente con opzioni disponibili return ( a === b.value || a === b || a.value === b || a.value === b.value ); }; } } }); this.chartsData = new Map(Object.entries(telemetryMap)); // setto expanded di default a true per i rimi due elementi Array.from(this.chartsData.keys()).forEach((key, index) => { if (index < 2) { this.chartsData!.set(key, { ...this.chartsData!.get(key), expanded: true, }); } }); this.setTableDataMap(); this.buildFormTelFilter(); } } getChartDataByTelemetryKey(key: string, getPredicted: boolean) { this.getChartDataByTelemetryKeyObservable(key) ?.pipe(catchError((error: any) => of(error))) .subscribe({ next: (res: any) => { let tempTelemtries: any = {}; // variabile di appoggio in cui verrà salvata la struttura: {nome_device: dati telemetria parsed} Object.keys(res).forEach((deviceName) => { let temp: any = {}; // variabile di appoggio in cui salvo la struttura { nome_device: dati telemtria non parsed} let temp1: any = {}; // variabile di appoggio in cui salvo i dati di telemetria parsed per il lib-chart component if (res[deviceName].telemetry) { temp[deviceName] = res[deviceName].telemetry[key]; temp1 = this.chartService.parseData([deviceName], temp); tempTelemtries[deviceName] = temp1[deviceName]; } }); this.chartsData!.set(key, { ...this.chartsData!.get(key), telemetries: tempTelemtries, }); this.getAnomalyData(key); if (getPredicted) { const predictiveInfo: { predictiveCaptureInterval: string; predictiveModel: string; predictiveTimeValue: string; } = this.chartsData!.get(key)?.predictiveForm?.value; let predictedTelemetry = `predicted_avg_${predictiveInfo.predictiveCaptureInterval}_${key}_${predictiveInfo.predictiveModel}`; if (predictiveInfo.predictiveTimeValue !== 'present') { predictedTelemetry += `_${predictiveInfo.predictiveTimeValue}`; } this.getTelemetriesDataByTelemetryKey(key, predictedTelemetry); } }, error: (err: any) => { console.error(err); }, }); } getChartDataByTelemetryKeyObservable(telemetryKey: string) { const deviceTelemetry = this.dashboard?.telemetry_device?.find( (elem) => elem.telemetry?.name === telemetryKey ); if (deviceTelemetry) { let devices = deviceTelemetry.devices; if (this.chartsData) { devices = devices?.filter((dev) => this.chartsData!.get(telemetryKey)?.telemetryKeys?.find( (devKey) => dev.name === devKey ) ); } if (devices && devices.length) { const devicesTelemetryMap: any = {}; devices.forEach((device) => { devicesTelemetryMap[device.name!] = this.readTelemetryService.getEntityHistoricalTimeseriesUsingPost({ uuidDevice: device.uuid!, body: { startTs: moment(this.rangeSelected.startDate).valueOf(), endTs: moment(this.rangeSelected.endDate).valueOf(), telemetryKeys: [telemetryKey], aggregationInterval: moment(this.rangeSelected.endDate).valueOf() - moment(this.rangeSelected.startDate).valueOf(), }, }); }); return forkJoin(devicesTelemetryMap); } else return null; } else return null; } getTelemetriesDataByTelemetryKey( telemetryKey: string, predictedTelemetryKey: string, changedPredictedInfo?: boolean ) { this.getTelemetriesDataByTelemetryKeyObservable(predictedTelemetryKey) ?.pipe(catchError((error: any) => of(error))) .subscribe({ next: (res: any) => { let tempTelemtries: any = {}; let tempTelemetryKeys: string[] = []; // variabile di appoggio in cui verrà salvata la struttura: {nome_device: dati telemetria parsed} Object.keys(res).forEach((deviceName) => { let temp: any = {}; // variabile di appoggio in cui salvo la struttura { nome_device: dati telemtria non parsed} let temp1: any = {}; // variabile di appoggio in cui salvo i dati di telemetria parsed per il lib-chart component if ( res[deviceName].telemetry && this.chartsData!.get(telemetryKey) ?.form?.get('device') ?.value?.find((dev: FormSelectOption) => deviceName.includes(dev.translate) ) ) { temp[deviceName] = res[deviceName].telemetry[predictedTelemetryKey]; temp1 = this.chartService.parseData([deviceName], temp); tempTelemtries[deviceName] = temp1[deviceName]; tempTelemetryKeys.push(deviceName); } }); const tempChartsData = { ...this.chartsData?.get(telemetryKey) }; // rimuovo eventuali telemetrie di predizione precedenti tempChartsData.telemetryKeys = tempChartsData.telemetryKeys?.filter( (key) => !key.includes('predicted') ); Object.keys(tempChartsData.telemetries!).forEach((key) => { if (key.includes('predicted')) delete tempChartsData.telemetries![key]; }); this.chartsData!.set(telemetryKey, undefined); setTimeout(() => { this.chartsData!.set(telemetryKey, { ...tempChartsData, telemetries: { ...tempChartsData.telemetries, ...tempTelemtries }, telemetryKeys: tempChartsData.telemetryKeys?.concat(tempTelemetryKeys), }); }, 50); }, error: (err: any) => { console.error(err); }, }); } getTelemetriesDataByTelemetryKeyObservable(telemetryKey: string) { const deviceTelemetry = this.dashboard?.telemetry_device?.find( (elem) => elem.telemetry?.name === telemetryKey ); if (deviceTelemetry) { let devices = deviceTelemetry.devices; if (devices && devices.length) { const devicesTelemetryMap: any = {}; devices.forEach((device) => { devicesTelemetryMap[telemetryKey + '_' + device.name!] = this.readTelemetryService.getEntityHistoricalTimeseriesUsingPost({ uuidDevice: device.uuid!, body: { startTs: moment(this.rangeSelected.startDate).valueOf(), endTs: moment(this.rangeSelected.endDate).valueOf(), telemetryKeys: [telemetryKey], aggregationInterval: moment(this.rangeSelected.endDate).valueOf() - moment(this.rangeSelected.startDate).valueOf(), }, }); }); return forkJoin(devicesTelemetryMap); } else return null; } else return null; } getChartConfiguration(telemetryInfo: TelemetryStruct) { return new ChartConfiguration( telemetryInfo.name, TypeChart.LINE, null, { valueType: AxisType.DateTime, intervalType: intervalType.AUTO, }, { title: this.translateService.instant(telemetryInfo.name), labelFormat: `{value} ${this.translateService.instant( telemetryInfo.unit )}`, }, { enable: true, shared: true, format: '${series.name} : ${point.x} : ${point.y}', }, { enable: true, lineType: LineTypeCrossHair.VERTICAL, }, null, { enableMouseWheelZooming: true, enablePinchZooming: true, enableSelectionZooming: true, enablePan: true, mode: ModeTypeZoom.X, }, { visible: true, position: LegendPosition.BOTTOM, shape: ShapeLegend.HORIZONTAL_LINE, }, [ '#4273db', '#42db6f', '#802c1f', '#d942db', '#d2ff00', '#d942db', '#ffc4bd', '#ff533d', ] ); } getPredictedInfoByTelemetryKey(key: string): { predictiveCaptureInterval: string; predictiveModel: string; predictiveTimeValue: string; } { return this.chartsData!.get(key)?.predictiveForm?.value; } getPredictedTelemetryByKey(key: string): string { const predictiveInfo = this.getPredictedInfoByTelemetryKey(key); let predictedTelemetry = `predicted_avg_${predictiveInfo.predictiveCaptureInterval}_${key}_${predictiveInfo.predictiveModel}`; if (predictiveInfo.predictiveTimeValue !== 'present') { predictedTelemetry += `_${predictiveInfo.predictiveTimeValue}`; } return predictedTelemetry; } getAnomalyInfo(key: string): | { predictiveCaptureInterval: string; predictiveModel: string; } | undefined { return this.chartsData?.get(key)?.tableData?.form?.value; } getAnomalyTelemetryKeys(key: string): string[] { return [ this.getAnomalyTelemetryKey(key), this.getAnomalyTelemetryValueKey(key), this.getAnomalyTelemetryPredictedValueKey(key), this.getAnomalyTelemetryPredictedFutureValueKey(key), ]; } getAnomalyTelemetryKey(key: string): string { const anomalyInfo = this.getAnomalyInfo(key); if (anomalyInfo) { return `anomaly_avg_${anomalyInfo.predictiveCaptureInterval}_${key}_${anomalyInfo.predictiveModel}`; } else return ''; } getAnomalyTelemetryValueKey(key: string): string { const anomalyTelemetryKey = this.getAnomalyTelemetryKey(key); if (anomalyTelemetryKey) { const splittedByUnderscoreValues = anomalyTelemetryKey.split('_'); if (splittedByUnderscoreValues.length >= 3) { return ( splittedByUnderscoreValues[1] + '_' + splittedByUnderscoreValues[2] + '_' + key ); } else return ''; } else return ''; } getAnomalyTelemetryPredictedValueKey(key: string): string { return `predicted_avg_${ this.getAnomalyInfo(key)?.predictiveCaptureInterval }_${key}_${this.getAnomalyInfo(key)?.predictiveModel}`; } getAnomalyTelemetryPredictedFutureValueKey(key: string): string { return `predicted_avg_${ this.getAnomalyInfo(key)?.predictiveCaptureInterval }_${key}_${this.getAnomalyInfo(key)?.predictiveModel}_future_60min`; } getCurrentTableDataByTelemetryKey(key: string) { if ( this.chartsData && this.chartsData.get(key) && this.chartsData.get(key)!.tableData && this.chartsData.get(key)!.tableData!.devices ) { return this.chartsData!.get(key)!.tableData!.devices.find( (elem) => elem.device.uuid === this.chartsData!.get(key)!.currentTableDevice?.uuid ); } else return undefined; } isTelemetryPredictable(key: string) { return this.predictableTelemetryKeys.find( (telemetryKey) => telemetryKey === key ); } onTelemetryOpened(key: string) { this.chartsData!.set(key, { ...this.chartsData!.get(key), expanded: true }); this.getChartDataByTelemetryKeyObservable(key) ?.pipe(catchError((error: any) => of(error))) .subscribe({ next: (res: any) => { let tempTelemetries: any = {}; // variabile di appoggio in cui verrà salvata la struttura: {nome_device: dati telemetria parsed} Object.keys(res).forEach((deviceName) => { let temp: any = {}; // variabile di appoggio in cui salvo la struttura { nome_device: dati telemtria non parsed} let temp1: any = {}; // variabile di appoggio in cui salvo i dati di telemetria parsed per il lib-chart component if (res[deviceName].telemetry) { temp[deviceName] = res[deviceName].telemetry[key]; temp1 = this.chartService.parseData([deviceName], temp); tempTelemetries[deviceName] = temp1[deviceName]; } else { // se non ci sono telemetrie per il device tempTelemetries[deviceName] = { data: [], }; } }); this.chartsData!.set(key, { ...this.chartsData!.get(key), telemetries: tempTelemetries, }); this.getAnomalyData(key); }, error: (err: any) => { console.error(err); }, }); } onTelemetryClosed(key: string) { this.chartsData!.set(key, { ...this.chartsData!.get(key), expanded: false, }); } setTableDataMap() { let mapTemp: any = {}; if (this.dashboard && this.chartsData && this.anomalyTelemetryMap) { Array.from(this.chartsData.keys()).forEach((key) => { if ( !key.includes('predicted') && !key.includes('avg') && Array.from(this.anomalyTelemetryMap!.keys()).find((telemetryKey) => telemetryKey.includes(key) ) ) { if (this.dashboard && this.dashboard.telemetry_device) { const telemetryDevice = this.dashboard.telemetry_device.find( (elem) => elem.telemetry?.name === key ); if (telemetryDevice && telemetryDevice.devices) { mapTemp[key] = { unit: telemetryDevice.telemetry?.unit, devices: telemetryDevice.devices.map((device) => { return { device, data: [], totalNumber: 0, pageSize: 10, pageNumber: 0, currentPageData: [], configurationPaginator: { ...this.configurationPaginator }, }; }), configurationTabGroup: { configuration: telemetryDevice.devices.map((device) => { const tabConf: TabConfiguration = { id: device.uuid ?? '', key: device.name ?? '', tab_label: { label: device.name ?? '', tooltip: device.description ?? '', }, component: ['anomalyTable'], }; return tabConf; }), }, formInputs: JSON.parse( JSON.stringify( formsInputConfiguration[formsName.DASHBOARD_ANOMALY_FORM] ) ), }; mapTemp[key]['form'] = this.formService.buildForm( mapTemp[key]['formInputs'] ); } } } }); this.tableDataMap = new Map(Object.entries(mapTemp)); this.tableDataMap.forEach((tableValue, tableKey) => { tableValue.form.valueChanges.subscribe( (value: { predictiveModel: string; predictiveCaptureInterval: string; }) => { this.getAnomalyData(tableKey); } ); }); this.chartsData.forEach((chartDataValue, chartDataKey) => { if (this.tableDataMap!.has(chartDataKey)) { this.chartsData?.set(chartDataKey, { ...chartDataValue, tableData: this.tableDataMap!.get(chartDataKey), currentTableDevice: this.tableDataMap!.get(chartDataKey)?.devices[0].device, }); } }); // inizializzo dati tabella anomalie this.chartsData.forEach((chartDataValue, chartDataKey) => { if (chartDataValue?.expanded && chartDataValue.tableData) { this.getAnomalyData(chartDataKey); } }); } } onAnomalyTabChangedByTelemetryKey( telemetryKey: string, tab: TabConfiguration ) { if (this.chartsData?.get(telemetryKey)) { this.chartsData!.get(telemetryKey)!.currentTableDevice = { name: tab.key, uuid: tab.id, }; } this.getAnomalyData(telemetryKey); } loadTableAnomalyData(event: any, key: string) { const tableData = this.getCurrentTableDataByTelemetryKey(key); if (tableData) { tableData!.totalNumber = tableData!.data.length; tableData!.pageNumber = event.pageCount; tableData!.pageSize = event.pageSize; tableData!.currentPageData = tableData!.data.slice( 0 + tableData!.pageNumber * tableData!.pageSize, 0 + tableData!.pageNumber * tableData!.pageSize + tableData!.pageSize ); } } goBack() { this.router.navigateByUrl('dashboard'); } //// SELECTION CONF buildFormTelFilter() { [...this.chartsData!.keys()].forEach((e) => { // escludo telemetrie di predizone, anomalia e mediaa if ( !e.includes('predicted') && !e.includes('anomaly') && !e.includes('avg') ) { this.telemetriesList.push({ value: e, translate: e }); } }); this.ficTL = [ { name: 'TelemetryList', type: 'select_multiple', default: '', validators: [Validators.nullValidator], width: 'col-12', options: this.telemetriesList, translate: { label: 'Filtro Telemetrie', }, }, ]; this.formTL = this.formService.buildForm(this.ficTL); this.formTL?.controls['TelemetryList'].valueChanges.subscribe( (value: string[]) => { this.showSelection = value; } ); /// preseleziona i valori this.formTL?.get('TelemetryList')?.setValue([...this.chartsData!.keys()]); } ngAfterViewInit(): void { // elemento input del date range picker if (this.inputDateRangePicker) this.inputDateRangePicker.readOnly = true; //setto a readonly per poterne cambiare il valore solo da popup // inizializzo (ultime 24h) this.dateControl.setValue([ new Date( new Date().getFullYear(), new Date().getMonth(), new Date().getDate(), new Date().getHours() - 24, new Date().getMinutes() ), new Date(), ]); this.rangeSelected.startDate = this.dateControl.value[0]; this.rangeSelected.endDate = this.dateControl.value[1]; this.dateRangePicker.activeIndex = 0; this.dateControl.valueChanges.subscribe((val: Date[]) => { this.rangeSelected.startDate = val[0]; this.rangeSelected.endDate = val[1]; }); // apro di default i primi due accordion if (this.accordion && this.accordion._headers) { Array.from(this.accordion._headers).forEach((accordionHeader, index) => { if (index < 2) { accordionHeader.panel.open(); } }); } } onClose(event: any) { if (this.dateRangePicker.activeIndex <= 3) { setTimeout(() => { this.dateRangePicker.value = this.dateRangePickerConfiguration.ranges.map( (range: { start: any; end: any }) => { return [range.start, range.end]; } )[this.dateRangePicker.activeIndex]; this.openedTelemetryKeys.forEach((key) => { this.getChartDataByTelemetryKey( key, this.chartsData?.get(key)?.form?.get('predicted')?.value ); }); }, 5); } } getAnomalyData(key: string) { const currentTableDevice = this.chartsData && this.chartsData.get(key) && this.chartsData.get(key)!.currentTableDevice ? this.chartsData.get(key)!.currentTableDevice : undefined; const tableData = this.getCurrentTableDataByTelemetryKey(key); if (currentTableDevice) { this.readTelemetryService .getEntityHistoricalTimeseriesUsingPost({ uuidDevice: currentTableDevice.uuid!, body: { startTs: moment(this.rangeSelected.startDate).valueOf(), endTs: moment(this.rangeSelected.endDate).valueOf(), telemetryKeys: this.getAnomalyTelemetryKeys(key), aggregationInterval: moment(this.rangeSelected.endDate).valueOf() - moment(this.rangeSelected.startDate).valueOf(), }, }) .subscribe({ next: (res) => { if (res?.telemetry) { if (tableData) { tableData.data = this.getAnomalyTableData(res.telemetry!); // info paginazione tableData!.totalNumber = tableData!.data.length; tableData!.currentPageData = tableData!.data.slice( 0 + tableData!.pageNumber * tableData!.pageSize, 0 + tableData!.pageNumber * tableData!.pageSize + tableData!.pageSize ); tableData!.configurationPaginator.length = tableData!.totalNumber; } } else { if (tableData) { tableData!.data = []; tableData!.currentPageData = []; tableData!.configurationPaginator.length = 0; } } }, error: (err) => { console.error(err); }, }); } } /* prendo la chiave di telemetria per la quale il numero di dati in risposta è minore, a partire da questa scrorro tutte le altre per trovare i timestamp in comune e poi uso una mappa dove ad ogni timestamp associo i valori di tutte e 4 le telemetrie. A partire da questa mappa poi mi creo l'aray di dati che andrà a popolare la tabella di anomalie*/ getAnomalyTableData(telemetryMap: { [key: string]: TsValuePair[] }): { anomalyValue?: number; telemetryPredictedValue?: number; telemetryPredictedFutureValue?: number; telemetryValue?: number; telemetryTs: number; }[] { let data: { anomalyValue?: number; telemetryPredictedValue?: number; telemetryPredictedFutureValue?: number; telemetryValue?: number; telemetryTs: number; }[] = []; const telemeryKeys = Object.keys(telemetryMap); let shorterKey = telemeryKeys[0]; telemeryKeys.forEach((valueKey) => { if (telemetryMap[valueKey].length < telemetryMap[shorterKey].length) { shorterKey = valueKey; } }); const mergedElementsByTS: any = {}; telemetryMap[shorterKey].forEach((value) => { mergedElementsByTS[value.telemetryTs!] = {}; mergedElementsByTS[value.telemetryTs!][shorterKey] = value.telemetryValue; telemeryKeys .filter((valueKey) => valueKey !== shorterKey) .forEach((val) => { const found = telemetryMap[val].find((elem) => { return elem.telemetryTs === value.telemetryTs; }); if (found) { mergedElementsByTS[value.telemetryTs!][val] = found.telemetryValue; } }); }); Object.keys(mergedElementsByTS).forEach((_key) => { const valueToAdd: any = { telemetryTs: Number(_key), }; Object.keys(mergedElementsByTS[_key]).forEach((innerKey) => { valueToAdd[innerKey] = mergedElementsByTS[_key][innerKey]; data.push(valueToAdd); }); }); data = data.map((elem: any) => { const mappedValue: { anomalyValue?: number; telemetryPredictedValue?: number; telemetryPredictedFutureValue?: number; telemetryValue?: number; telemetryTs: number; } = { telemetryTs: elem.telemetryTs }; Object.keys(elem).forEach((objectKey) => { if (objectKey !== 'telemetryTs') { if (objectKey.includes('anomaly')) { // anomalyValue mappedValue.anomalyValue = elem[objectKey]; } else if ( objectKey.includes('predicted') && objectKey.includes('future_60min') ) { // telemetryPredictedFutureValue mappedValue.telemetryPredictedFutureValue = elem[objectKey]; } else if (objectKey.includes('predicted')) { // telemetryPredictedValue mappedValue.telemetryPredictedValue = elem[objectKey]; } else { // telemetryValue mappedValue.telemetryValue = elem[objectKey]; } } }); return mappedValue; }); return data; } updateDashboard() { if (this.chartsData) { Array.from(this.chartsData!.keys()) .filter((key) => { return this.chartsData!.get(key)?.expanded; }) .forEach((key) => { this.getChartDataByTelemetryKey( key, this.chartsData?.get(key)?.form?.get('predicted')?.value && this.isTelemetryPredictable(key) ); }); } //window.location.reload(); } }
Editor is loading...