dev smartfarming #1

Merged
agrilink merged 53 commits from development into main 2024-12-30 05:53:19 +00:00
3 changed files with 72 additions and 64 deletions
Showing only changes of commit a2befa2950 - Show all commits

View File

@ -20,7 +20,7 @@
<div class="sensor-wrapper">
<div class="title-with-dropdown">
<div class="title">Sensor NPK 1</div>
<select class="form-select" style="margin-top: 10px" [(ngModel)]="selectedNPK1" (change)="updateCharts()">
<select class="form-select" style="margin-top: 10px" [(ngModel)]="selectedNPK1" (change)="updateCharts(); onResize()">
<option value="npk">NPK</option>
<option value="others">Lainnya</option>
</select>
@ -39,7 +39,7 @@
<div class="sensor-wrapper">
<div class="title-with-dropdown">
<div class="title">Sensor NPK 2</div>
<select class="form-select" style="margin-top: 10px" [(ngModel)]="selectedNPK2" (change)="updateCharts()">
<select class="form-select" style="margin-top: 10px" [(ngModel)]="selectedNPK2" (change)="updateCharts(); onResize()">
<option value="npk">NPK</option>
<option value="others">Lainnya</option>
</select>

View File

@ -4,19 +4,33 @@
justify-content: flex-start;
height: max-content;
.sensor-wrapper {
position: relative;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 35px;
background-color: #f1f1f1;
border: 1px solid #E5E5E5;
padding: 0px 20px 0px 20px;
background-color: white;
border-radius: 10px;
h2 {
font-size: 18px;
margin-bottom: 10px;
}
canvas {
position: relative;
width: 100%;
height: auto;
aspect-ratio: 2 / 1;
max-height: 300px;
}
}
.title-with-dropdown {
display: flex;
@ -42,17 +56,11 @@
margin: 18px 0px 0px 0px;
}
canvas {
height: 500px !important;
width: 100%;
max-width: 2000px;
padding-bottom: 20px;
padding-top: 20px;
}
@media (max-width: 768px) {
canvas {
height: 300px !important;
height: auto;
width: 100%;
max-width: 100%;
}
}
@ -62,7 +70,7 @@ canvas {
}
.spinner {
color: #16423C
color: #16423C;
}
.no-data {

View File

@ -12,12 +12,12 @@ const parameterColors: { [key: string]: string } = {
vicihumidity: '#16423C',
viciluminosity: '#DF9B55',
soiltemperature: '#FF6347',
soilhumidity: '#00BFFF',
soilhumidity: '#0389b5',
soilconductivity: '#A52A2A',
soilph: '#228B22',
soilnitrogen: '#FEDC56',
soilnitrogen: '#fece48',
soilphosphorus: '#B80F0A',
soilpotassium: '#6F2DA8',
soilpotassium: '#4c1f74',
};
@Component({
@ -105,39 +105,45 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
const month = String(today.getMonth() + 1).padStart(2, '0');
const day = String(today.getDate()).padStart(2, '0');
const startEnd = `${year}-${month}-${day}`;
// const startEnd = '2024-10-24';
const timeRange = 'HOURLY';
Object.keys(this.charts).forEach(key => {
if (this.charts[key]) {
this.charts[key]?.destroy();
this.charts[key] = undefined;
}
});
// Fetch data for DHT
this.sensorService.getSensorData('dht', '', startEnd, timeRange).subscribe({
next: (response) => {
if (response.statusCode === 200 && response.data.dht?.length > 0) {
this.createChart(this.dhtChartElement.nativeElement, response, 'dht', 'npk');
this.isNoDataDHT = false;
this.allNoData = false;
} else {
this.isNoDataDHT = true;
}
this.isLoadingDHT = false;
this.isLoadingDHT = false;
if (response.statusCode === 200 && response.data.dht?.length > 0) {
this.createChart(this.dhtChartElement.nativeElement, response, 'dht', 'npk');
this.isNoDataDHT = false;
} else {
this.isNoDataDHT = true;
}
},
error: () => {
this.isLoadingDHT = false;
this.isNoDataDHT = true;
this.isLoadingDHT = false;
this.isNoDataDHT = true;
}
});
});
// Fetch data for NPK1
this.sensorService.getSensorData('npk1', '', startEnd, timeRange).subscribe({
next: (response) => {
this.isLoadingNPK1 = false;
if (response.statusCode === 200 && response.data.npk1?.length > 0) {
this.createChart(this.npk1ChartElement.nativeElement, response, 'npk1', this.selectedNPK1);
this.isNoDataNPK1 = false;
this.allNoData = false;
} else {
this.isNoDataNPK1 = true;
}
this.isLoadingNPK1 = false;
},
error: () => {
this.isLoadingNPK1 = false;
@ -148,14 +154,14 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
// Fetch data for NPK2
this.sensorService.getSensorData('npk2', '', startEnd, timeRange).subscribe({
next: (response) => {
this.isLoadingNPK2 = false;
if (response.statusCode === 200 && response.data.npk2?.length > 0) {
console.log(this.selectedNPK2);
this.createChart(this.npk2ChartElement.nativeElement, response, 'npk2', this.selectedNPK2);
this.isNoDataNPK2 = false;
this.allNoData = false;
} else {
this.isNoDataNPK2 = true;
}
this.isLoadingNPK2 = false;
},
error: () => {
this.isLoadingNPK2 = false;
@ -163,6 +169,8 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
}
});
}
createChart(canvas: HTMLCanvasElement, response: ApiResponse, sensor: string, selectedOption: string): void {
const ctx = canvas.getContext('2d');
@ -176,8 +184,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
let datasets: any[] = [];
if (sensor === 'dht') {
// Handle DHT parameters directly
datasets = ['vicitemperature', 'vicihumidity', 'viciluminosity'].map(parameter => {
datasets = ['vicitemperature', 'viciluminosity', 'vicihumidity'].map(parameter => {
const { data, labels } = this.getDataFromResponse(response, sensor, parameter);
if (data.length === 0) {
@ -202,21 +209,27 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
};
}).filter(dataset => dataset !== null);
} else {
// Handle NPK1 and NPK2 as before
datasets = parameters.map(parameter => {
const { data, labels } = this.getDataFromResponse(response, sensor, parameter);
if (data.length === 0) {
console.warn(`No data found for parameter: ${parameter}`);
return null;
}
datasets = parameters
.filter(parameter => {
if (selectedOption === 'npk') {
return ['soilphosphorus', 'soilnitrogen', 'soilpotassium'].includes(parameter);
} else if (selectedOption === 'others') {
return !['soilphosphorus', 'soilnitrogen', 'soilpotassium'].includes(parameter);
}
return true;
})
.map(parameter => {
const { data, labels } = this.getDataFromResponse(response, sensor, parameter);
if (data.length === 0) {
console.warn(`No data found for parameter: ${parameter}`);
return null;
}
const displayName = this.parameterDisplayNames[parameter] || parameter;
const borderColor = parameterColors[parameter] || '#000000';
const backgroundColor = `${borderColor}4D`;
const displayName = this.parameterDisplayNames[parameter] || parameter;
const borderColor = parameterColors[parameter] || '#000000';
const backgroundColor = `${borderColor}4D`;
// Filter datasets based on the selected option
if (selectedOption === 'npk' && ['soilphosphorus', 'soilnitrogen', 'soilpotassium'].includes(parameter)) {
return {
label: displayName,
data,
@ -228,22 +241,8 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
pointRadius: 0,
pointHoverRadius: 0,
};
} else if (selectedOption === 'others' && !['soilphosphorus', 'soilnitrogen', 'soilpotassium'].includes(parameter)) {
return {
label: displayName,
data,
borderColor,
borderWidth: 1.5,
fill: true,
backgroundColor,
tension: 0.5,
pointRadius: 0,
pointHoverRadius: 0,
};
}
return null;
}).filter(dataset => dataset !== null);
})
.filter(dataset => dataset !== null);
}
if (datasets.length === 0) {
@ -264,6 +263,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
options: {
responsive: true,
maintainAspectRatio: false,
aspectRatio: 2,
plugins: {
tooltip: {
enabled: true,
@ -285,7 +285,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy {
}
}
});
}
}
getDataFromResponse(response: ApiResponse, sensor: string, parameter: string): { data: number[], labels: string[] } {
const sensorData = response.data[sensor as keyof typeof response.data];