frontend-smartfarming/agrilink_vocpro/src/app/pages/dashboard/page/graph/graph.component.ts

212 lines
6.7 KiB
TypeScript
Raw Normal View History

import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
import { Chart, registerables } from 'chart.js';
import { SensorService } from '../../../../cores/services/sensor.service';
import { ApiResponse, ParameterSensor} from '../../../../cores/interface/sensor-data';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
Chart.register(...registerables);
const parameterColors: { [key: string]: string } = {
vicitemperature_avg: '#8F5A62',
vicihumidity_avg: '#16423C',
viciluminosity_avg: '#DF9B55',
soiltemperature_avg: '#8F5A62',
soilhumidity_avg: '#54909c',
soilconductivity_avg: '#661311',
soilph_avg: '#664735',
soilnitrogen_avg: '#3a6635',
soilphosphorus_avg: '#3f3566',
soilpotassium_avg: '#5f3566',
};
2024-09-17 06:50:34 +00:00
@Component({
selector: 'app-graph',
standalone: true,
imports: [CommonModule, FormsModule],
2024-09-17 06:50:34 +00:00
templateUrl: './graph.component.html',
styleUrls: ['./graph.component.scss']
2024-09-17 06:50:34 +00:00
})
export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild('myChart', { static: false }) chartElement!: ElementRef<HTMLCanvasElement>;
selectedSensor: string = '';
selectedParameter: string = '';
parameters: string[] = [];
isLoading: boolean = true;
2024-09-17 06:50:34 +00:00
sensorParameters: { [key: string]: string[] } = {
dht: ['vicitemperature_avg', 'vicihumidity_avg', 'viciluminosity_avg'],
npk1: ['soiltemperature_avg', 'soilhumidity_avg', 'soilconductivity_avg', 'soilph_avg', 'soilnitrogen_avg', 'soilphosphorus_avg', 'soilpotassium_avg'],
npk2: ['soiltemperature_avg', 'soilhumidity_avg', 'soilconductivity_avg', 'soilph_avg', 'soilnitrogen_avg', 'soilphosphorus_avg', 'soilpotassium_avg'],
};
2024-09-17 06:50:34 +00:00
parameterDisplayNames: { [key: string]: string } = {
vicitemperature_avg: 'Temperature (°C)',
vicihumidity_avg: 'Humidity (%)',
viciluminosity_avg: 'Luminosity (lx)',
soiltemperature_avg: 'Soil Temperature (°C)',
soilhumidity_avg: 'Soil Humidity (%)',
soilconductivity_avg: 'Conductivity (mS/cm)',
soilph_avg: 'pH',
soilnitrogen_avg: 'Nitrogen (PPM)',
soilphosphorus_avg: 'Phosphorus (PPM)',
soilpotassium_avg: 'Potassium (PPM)',
};
2024-09-17 06:50:34 +00:00
chart: Chart | undefined;
labelsHourly: string[] = [];
private resizeListener!: () => void;
2024-09-17 06:50:34 +00:00
constructor(private sensorService: SensorService) {}
2024-09-17 06:50:34 +00:00
ngOnInit(): void {
this.selectedSensor = 'dht';
this.updateParameters();
this.selectedParameter = 'vicitemperature_avg';
this.updateChart();
this.resizeListener = this.onResize.bind(this);
window.addEventListener('resize', this.resizeListener);
2024-09-17 06:50:34 +00:00
}
ngAfterViewInit(): void {
this.updateChart();
}
2024-09-17 06:50:34 +00:00
ngOnDestroy(): void {
window.removeEventListener('resize', this.resizeListener);
}
onResize(): void {
if (this.chart) {
this.chart.destroy();
this.updateChart();
}
}
getDataFromResponse(response: ApiResponse, sensor: string, parameter: string): { data: number[], labels: string[] } {
const sensorData = response.data[sensor as keyof typeof response.data];
const data: number[] = [];
const labels: string[] = [];
if (sensorData) {
sensorData.forEach(item => {
data.push(item[parameter as keyof ParameterSensor] ?? 0);
labels.push(`${item.hour}.00`);
});
} else {
console.error('No data found for sensor:', sensor);
}
return { data, labels };
}
createChart(data: number[], parameter: string, labels: string[]): void {
const canvas = this.chartElement.nativeElement;
2024-09-17 06:50:34 +00:00
const ctx = canvas.getContext('2d');
if (this.chart) {
this.chart.destroy();
2024-09-17 06:50:34 +00:00
}
if (ctx) {
const displayName = this.parameterDisplayNames[parameter] || parameter;
const borderColor = parameterColors[parameter] || '#000000';
const backgroundColor = `${borderColor}4D`;
2024-09-17 06:50:34 +00:00
this.chart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: displayName,
2024-09-17 06:50:34 +00:00
data,
borderColor,
borderWidth: 1.5,
fill: true,
backgroundColor,
tension: 0.5,
pointRadius: 0,
pointHoverRadius: 0,
2024-09-17 06:50:34 +00:00
pointBackgroundColor: borderColor,
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
tooltip: {
enabled: true,
mode: 'nearest',
intersect: false,
callbacks: {
label: (tooltipItem) => {
const paramLabel = displayName;
const value = tooltipItem.formattedValue;
return `${paramLabel}: ${value}`;
}
}
2024-09-17 06:50:34 +00:00
},
legend: { display: false }
},
scales: {
x: { grid: { display: false }, beginAtZero: true },
y: { grid: { display: false }, beginAtZero: true }
2024-09-17 06:50:34 +00:00
}
}
});
}
}
getParameterKey(displayName: string): string {
return Object.keys(this.parameterDisplayNames).find(key => this.parameterDisplayNames[key] === displayName) || '';
}
onSensorChange(event: Event): void {
const select = event.target as HTMLSelectElement;
this.selectedSensor = select.value;
this.updateParameters();
if (this.selectedSensor === 'dht') {
this.selectedParameter = 'vicitemperature_avg';
} else if (this.selectedSensor === 'npk1' || this.selectedSensor === 'npk2') {
this.selectedParameter = 'soiltemperature_avg';
}
this.updateChart();
}
2024-09-17 06:50:34 +00:00
updateParameters(): void {
this.parameters = this.sensorParameters[this.selectedSensor].map(param => this.parameterDisplayNames[param]);
this.selectedParameter = this.parameters[1];
}
2024-09-17 06:50:34 +00:00
updateChart(): void {
this.isLoading = true;
const today = new Date();
const year = today.getFullYear();
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
const startEnd= `${year}-${month}-${day}`;
const timeRange = 'HOURLY';
this.sensorService.getSensorData(this.selectedSensor, this.selectedParameter, startEnd, timeRange).subscribe(
(response: ApiResponse) => {
if (response.statusCode === 200) {
const { data, labels } = this.getDataFromResponse(response, this.selectedSensor, this.selectedParameter);
this.createChart(data, this.selectedParameter, labels);
} else {
console.error('Error fetching data:', response.message);
}
this.isLoading = false;
},
(error) => {
console.error('API Error:', error);
this.isLoading = false;
}
);
2024-09-17 06:50:34 +00:00
}
}