Search code examples
angularchartschart.jshttpclientreal-time

Update data from server for ChartJS graph


For few days I've a problem with my Angular website. My goal is to receive data from a S7-1500 to display in real time data on a TV.

I success to have some datas in real time but I block on a little problem. When I change page, the data are refreshing on the graph, but if I stay on the same page, nothing happend.

In this service, I get data from an API and I put the "consoAir" at the end of an Array of 10 :

import {BehaviorSubject, combineLatest, forkJoin, timer} from 'rxjs';
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {switchMap} from 'rxjs/operators';

@Injectable()
export class LineService{
  constructor(private http: HttpClient) {
    this.getData();
  }

  _consoAir = [ Array(10).fill(0),
                Array(10).fill(0),
                Array(10).fill(0),
                Array(10).fill(0),
                Array(10).fill(0),
                Array(10).fill(0)];
  lineSubject = new BehaviorSubject<RcvData[]>([]);

  getData(): void {
    const lists: string[] = [
      'assets/donnee-l1.csv',
      'assets/donnee-l2.csv',
      'assets/donnee-l3.csv',
      'assets/donnee-l4.csv',
      'assets/donnee-l5.csv',
      'https://192.168.0.2/DataLogs?Path=/DataLogs/MyDataLog9.csv&Action=DOWNLOAD&E=1'
    ];
    const reqs$ = lists.map(list => this.http.get(list, {responseType: 'text'}));

    timer(0, 5000).pipe(
      switchMap(_ => forkJoin(reqs$))
    ).subscribe(listResults => {
        const parsedListResults = listResults.map(data => {
          const csvToRowArray = data.split('\n');
          const lastRow = csvToRowArray[csvToRowArray.length - 2];
          const row = lastRow.split(',');
          return new RcvData(
            parseInt(row[0], 10),
            row[1], row[2], parseInt(row[3], 10), row[4], row[5], row[6], row[7],
            parseInt(row[8], 10),
            parseInt(row[9], 10),
            parseInt(row[10], 10),
            parseInt(row[11], 10),
            parseFloat(row[12]),
            parseFloat(row[13]),
            parseFloat(row[14]),
            parseFloat(row[15]),
            parseFloat(row[16]),
            parseInt(row[17], 10));
        });
        this.lineSubject.next(parsedListResults);

        for (const module of parsedListResults) {
          this._consoAir[module.id - 1].push(module.consoAir);

          if (this._consoAir[module.id - 1].length > 10){
            this._consoAir[module.id - 1].splice(0, 1);
          }
        }
        console.log(this._consoAir);

      });
  }
}




class RcvData{
  seqNo: number;
  date: string;
  utcTime: string;
  id: number;
  name: string;
  refCharge: string;
  refDecharge: string;
  quantiteEnCours: string;
  quantiteHoraireReel: number;
  quantiteHoraireTheorique: number;
  quantitePosteReel: number;
  quantitePosteTheorique: number;
  trpHeureReel: number;
  trpPosteReel: number;
  trpObjectif: number;
  consoAir: number;
  consoElec: number;
  status: number;


  constructor(
    seqNo: number,
    date: string,
    utcTime: string,
    id: number,
    name: string,
    refCharge: string,
    refDecharge: string,
    quantiteEnCours: string,
    quantiteHoraireReel: number,
    quantiteHoraireTheorique: number,
    quantitePosteReel: number,
    quantitePosteTheorique: number,
    trpHeureReel: number,
    trpPosteReel: number,
    trpObjectif: number,
    consoAir: number,
    consoElec: number,
    status: number)
  {
    this.seqNo = seqNo;
    this.date = date.replace(/ /g, '').replace(/"/g, '');
    this.utcTime = utcTime.replace(/ /g, '').replace(/"/g, '');
    this.id = id;
    this.name = name.replace(/"/g, '');
    this.refCharge = refCharge.replace(/ /g, '').replace(/"/g, '');
    this.refDecharge = refDecharge.replace(/ /g, '').replace(/"/g, '');
    this.quantiteEnCours = quantiteEnCours.replace(/ /g, '').replace(/"/g, '');
    this.quantiteHoraireReel = quantiteHoraireReel;
    this.quantiteHoraireTheorique = quantiteHoraireTheorique;
    this.quantitePosteReel = quantitePosteReel;
    this.quantitePosteTheorique = quantitePosteTheorique;
    this.trpHeureReel = trpHeureReel;
    this.trpPosteReel = trpPosteReel;
    this.trpObjectif = trpObjectif;
    this.consoAir = consoAir;
    this.consoElec = consoElec;
    this.status = status;
  }
}

In this ts, I want to receive array data from service to display that :

import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import { ChartType } from 'chart.js';
import { LineService } from '../services/line.service';
import {ActivatedRoute} from '@angular/router';
import {combineLatest, Subscription} from 'rxjs';
import {filter, map} from 'rxjs/operators';
import {log} from 'util';

@Component({
  selector: 'app-conso-graph',
  templateUrl: './conso-graph.component.html',
  styleUrls: ['./conso-graph.component.scss']
})
export class ConsoGraphComponent implements OnDestroy{

  lineSubscription: Subscription;
  id: number;
  consoAir: number;
  chartType: ChartType;
  chartOptions: any;
  _time: any[] = Array(10).fill(0);
  _consoAir: any[] = this.lineService._consoAir;
  
  constructor(private lineService: LineService,
              private route: ActivatedRoute) {
    this.chartIt();
  }

  _focusedData$ = combineLatest(
    this.lineService.lineSubject.pipe(filter(x => x.length > 0)),
    this.route.params.pipe(filter(x => !!x.id), map(x => x.id - 1))
  ).pipe(
    map(([csvs, id]) => csvs[id])
  );

  gestionData(): void {
    this.lineSubscription = this._focusedData$.subscribe(x => this.id = x.id);
    this._consoAir = this.lineService._consoAir;
    console.log(this._consoAir[5]);
  }

  async chartIt() {
    await this.gestionData();
    this.chartType = 'line';
  }

  chartClicked(e: any): void { }
  chartHovered(e: any): void { }

  ngOnDestroy(): void {
    this.lineSubscription.unsubscribe();
  }

}

And here, I display the graph in HTML :

<div class="doubleTrp">
    <canvas baseChart
            [chartType]="chartType"
            [datasets]="[
              {
              data: this._consoAir[this.id - 1], label: 'Consommation Air'
              }
            ]"
            [labels]="this._time"
            [colors]="[{
              backgroundColor: ['rgb(255, 182, 0)'],
              hoverBackgroundColor: ['rgb(185, 30, 30)'],
              borderWidth: 1
            }]"
            [options]="{
              responsive: true,
              cutoutPercentage: 100,
              title : {
                display: true,
                text: 'Consommation Air',
                fontSize: 25
              }
            }"
            [legend]="true"
            (chartHover)="chartHovered($event)"
            (chartClick)="chartClicked($event)">
    </canvas>
</div>

I tried SetInterval, Timer or other thing but in service, the array is changing in real time, but not in the graph component ...

Every example will be helpful to me. Thank by advance.


Solution

  • I find solution by doing that :

    [datasets]="[
                    {
                        data: [ graphikElec[0],
                                graphikElec[1],
                                graphikElec[2],
                                graphikElec[3],
                                graphikElec[4],
                                graphikElec[5],
                                graphikElec[6],
                                graphikElec[7],
                                graphikElec[8],
                                graphikElec[9]
                              ],
                              label: 'kWh'
                    },