| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- import {Component, ElementRef, HostListener, OnDestroy, OnInit, QueryList, Renderer2, ViewChildren} from '@angular/core';
- import {ActivatedRoute} from '@angular/router';
- import {map, tap} from 'rxjs/operators';
- import * as moment from 'moment-timezone';
- import {GraphLoader} from '../../shared/graph-loading/graphloader';
- import {SensorsService} from '../../shared/api/endpoints/services/sensors.service';
- import {HttpResponse} from '@angular/common/http';
- import {ToastService} from '../../shared/services/toast.service';
- import {Sensor} from '../../shared/api/endpoints/models/sensor';
- import {ObservationService} from '../../shared/api/endpoints/services/observation.service';
- import {SensorType} from '../../shared/api/endpoints/models/sensor-type';
- import {Subscription} from 'rxjs';
- import type {View} from 'vega';
- @Component({
- selector: 'app-unit',
- templateUrl: './unit.component.html',
- styleUrls: ['./unit.component.scss']
- })
- export class UnitComponent implements OnInit, OnDestroy {
- preselectedSensors: string;
- unitId: number;
- viewCount = 0;
- data = [];
- time = [];
- from: Date = moment().hour(0).minutes(0).subtract(7, 'days').toDate();
- to: Date = moment().toDate();
- today: Date = moment().toDate();
- observationsData: any[] = [];
- sensorGroups = [];
- selectedSensors: string[] = [];
- sensors: Sensor[];
- dateChanged = false;
- sensorTypes: SensorType[];
- unitDescription: string;
- subscription: Subscription[] = [];
- showIntervalError = false;
- // One flag per group
- showVega: Record<string, boolean> = {};
- showVegaCounter: Record<string, number> = {};
- graphViews: Record<string, View> = {};
- // Grab *all* containers that match the template ref vegaContainer
- @ViewChildren('vegaContainer') vegaContainers!: QueryList<ElementRef>;
- constructor(
- private activatedRoute: ActivatedRoute,
- private sensorService: SensorsService,
- private toastService: ToastService,
- private observationService: ObservationService,
- private route: ActivatedRoute,
- private renderer: Renderer2
- ) {
- this.getInitData();
- // get unit sensors and prepare them for view
- this.sensorService.getUnitSensors({ unit_id: this.unitId }).pipe(
- tap(sens => {
- this.sensors = sens;
- this.sensors.sort((a, b) => a.sensorId - b.sensorId);
- }),
- tap(() => {
- if (this.sensors && this.sensors.length > 0) {
- this.sensors.forEach(sensor => {
- const sensorType = sensor.sensorId.toString().slice(0, 5);
- if (!this.sensorGroups.some(group => group === sensorType)) { // create sensor groups only for unit sensors
- this.sensorGroups.push(sensorType);
- setTimeout(() => {
- GraphLoader.getGraph(null, null, null, '#vega_container_' + sensor.sensorId.toString().slice(0, 5), null);
- }, 0);
- }
- });
- }
- })
- ).toPromise().then();
- }
- /**
- * Fires on every resize event
- */
- @HostListener('window:resize', ['$event'])
- public onWindowResize(event: UIEvent): void {
- this.onResize();
- }
- private onResize() {
- const itemCount = Object.keys(this.graphViews).length;
- console.log('Number of entries:', itemCount);
- Object.entries(this.graphViews).forEach(([key, view]) => {
- // Process each pair here
- const sensorGroupElement = '#vega_container_' + key;
- const box = document.getElementById('vega_container_' + key);
- const boxWidth = box.getBoundingClientRect().width;
- const boxHeight = box.getBoundingClientRect().height;
- if (view) {
- const newWidth = box.getBoundingClientRect().width - 50;
- console.log('Key:', key, 'NewWidth:', newWidth);
- view.width(newWidth).height(300).runAsync();
- }
- });
- }
- /**
- * Unsubscribe after leaving
- */
- ngOnDestroy(): void {
- this.subscription.forEach(subs => subs.unsubscribe());
- }
- /**
- * Sets up default data
- */
- getInitData() {
- this.route.queryParams.subscribe(params => {
- if (params.unitDescription) {
- this.unitDescription = params.unitDescription;
- }
- });
- this.sensorService.getSensorTypes().toPromise().then(types => this.sensorTypes = types);
- this.unitId = parseInt(this.activatedRoute.snapshot.paramMap.get('unitId'), 10);
- }
- ngOnInit(): void {
- }
- /**
- * Shows get data button
- */
- onDateChanged() {
- if (moment(this.to).diff(moment(this.from), 'months') > 6){
- this.dateChanged = false;
- this.showIntervalError = true;
- }
- else if (this.to < this.from) {
- this.dateChanged = false;
- this.showIntervalError = true;
- }
- else{
- this.dateChanged = true;
- this.showIntervalError = false;
- }
- }
- /**
- * Gets data based on selected time range
- */
- showGraph(changedDate: boolean = true, changedSensor: string = null) {
- const range: Date[] = [this.from, this.to];
- this.getObservations(range, changedDate, changedSensor);
- }
- /**
- * Check button handler.
- * @param sensorId checked sensorId
- * @param event event for getting if checked or unchecked
- */
- async addSensorToGraph(sensorId: string, event) {
- const groupId = sensorId.toString().slice(0, 5);
- const sensorGroupElement = '#vega_container_' + groupId;
- // if the checkmark is checked then the graph will be displayed
- this.graphViews[groupId] = null;
- this.showVega[groupId] = false;
- if (event.checked.includes(sensorId.toString()))
- this.showVega[groupId] = true;
- const box = document.getElementById('vega_container_' + groupId);
- const boxWidth = box.getBoundingClientRect().width;
- const boxHeight = box.getBoundingClientRect().height;
- GraphLoader.setSize(boxWidth - 50, 300);
- if (!this.selectedSensors.find(sensId => sensId.toString().slice(0, 5) === groupId)) { // if group of sensors is empty show empty graph
- // GraphLoader.getAnalyticsGraph(null, null, null, sensorGroupElement);
- this.graphViews[groupId] = await GraphLoader.getGraph(null, null, null, sensorGroupElement, null);
- } else {
- // use observations data
- if (event.checked) { // if checked > add to graph
- if (this.observationsData.some(sens => sens.sensorId.toString() === sensorId)) { // if already data for selected sensor in memory
- this.graphViews[groupId] = await GraphLoader.getGraph(this.filteredSelectedSensors(groupId),
- this.filteredObservationData(groupId), this.filteredSensorsInfos(groupId), sensorGroupElement, false);
- } else { // get data from server for added sensor and show graph for selected sensors
- this.showGraph(false, sensorId);
- }
- } else { // remove sensor from graph
- this.graphViews[groupId] = await GraphLoader.getGraph(this.filteredSelectedSensors(groupId), this.filteredObservationData(groupId),
- this.filteredSensorsInfos(groupId), sensorGroupElement, false);
- }
- }
- // no data in graph -> the graph element will be destroyed
- if (!this.showVega[groupId]) {
- const container = document.getElementById(`vega_container_${groupId}`);
- if (container) {
- container.innerHTML = '';
- this.graphViews[groupId] = null;
- }
- console.log(`Cleared children of #vega_container_${groupId}`);
- }
- }
- /**
- * Filter observations data only fro selected sensors.
- * @param sensorGroupId id of changed sensor group
- */
- filteredObservationData(sensorGroupId: string): any {
- return this.observationsData.filter(sen => this.selectedSensors.includes(sen.sensorId.toString()) &&
- sen.sensorId.toString().slice(0, 5) === sensorGroupId);
- }
- /**
- * Filter only selected sensors for group of sensors
- * @param sensorGroupId group of sensors
- */
- filteredSelectedSensors(sensorGroupId: string): any {
- return this.selectedSensors.filter(sen => sen.toString().slice(0, 5) === sensorGroupId);
- }
- /**
- * Get sensors only for group
- * @param sensorGroupId group id
- */
- filteredSensorsInfos(sensorGroupId: string): any {
- return this.sensors.filter(sen => this.selectedSensors.includes(sen.sensorId.toString()) &&
- sen.sensorId.toString().slice(0, 5) === sensorGroupId);
- }
- /**
- * Gets data from observation endpoint
- * @param range from and to interval
- * @param changedDate determines if dates changed so we need refresh all data
- * @param changedSensorId if selecting sensor only fetch data for this server
- */
- getObservations(range: Date[], changedDate: boolean, changedSensorId: string) {
- if (changedDate) { // if changed date we need new data for all sensors
- this.observationsData = []; // empty observation data
- this.selectedSensors.forEach(selectSens => {
- this.observationEndpointRequest(selectSens, range);
- });
- } else { // add data for added sensor
- this.observationEndpointRequest(changedSensorId, range);
- }
- }
- /**
- * Endpoint request to get observation data for sensor
- * @param sensorId sensor id to get data
- * @param range from and to interval
- */
- observationEndpointRequest(sensorId: string, range: Date[]) {
- this.observationService.getObservation$Response({
- unit_id: this.unitId,
- sensor_id: parseInt(sensorId, 10),
- from: moment(range[0]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3),
- to: moment(range[1]).format('yyyy-MM-DD HH:mm:ssZ').slice(0, -3)
- }).pipe(
- map((response: HttpResponse<any>) => {
- if (response.status === 200) {
- return response.body;
- } else if (response.status === 204) {
- this.toastService.showWarningNoData();
- return response.body;
- } else {
- return false;
- }
- })
- ).subscribe(
- async observations => {
- if (observations) {
- const groupId = sensorId.toString().slice(0, 5);
- this.observationsData.push({
- sensorId, sensor:
- this.sensors.find(sens => sens.sensorId.toString() === sensorId.toString()), data: observations
- });
- const view = '#vega_container_' + sensorId.toString().slice(0, 5);
- this.graphViews[groupId] = await GraphLoader.getGraph(this.filteredSelectedSensors(groupId),
- this.filteredObservationData(groupId), this.filteredSensorsInfos(groupId), view, false);
- }
- }, err => this.toastService.showError(err.error.message));
- }
- }
|