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="sensor-wrapper">
<div class="title-with-dropdown"> <div class="title-with-dropdown">
<div class="title">Sensor NPK 1</div> <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="npk">NPK</option>
<option value="others">Lainnya</option> <option value="others">Lainnya</option>
</select> </select>
@ -39,7 +39,7 @@
<div class="sensor-wrapper"> <div class="sensor-wrapper">
<div class="title-with-dropdown"> <div class="title-with-dropdown">
<div class="title">Sensor NPK 2</div> <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="npk">NPK</option>
<option value="others">Lainnya</option> <option value="others">Lainnya</option>
</select> </select>

View File

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

View File

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