Untitled
unknown
plain_text
3 years ago
42 kB
13
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...