dev smartfarming #1
|
|
@ -62,7 +62,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="text-center-copyright">
|
||||
<div>©2024</div>
|
||||
<div>©2024 Agrilink</div>
|
||||
<div>Powered by <strong>Politeknik Negeri Malang</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,23 @@
|
|||
</div>
|
||||
<div class="sensor-wrapper">
|
||||
<div class="title">Sensor DHT</div>
|
||||
<div class="button-param">
|
||||
<button
|
||||
[ngClass]="{'active': activeButton === 'vicitemperature'}"
|
||||
(click)="filterData('vicitemperature')">
|
||||
Temperatur Udara
|
||||
</button>
|
||||
<button
|
||||
[ngClass]="{'active': activeButton === 'vicihumidity'}"
|
||||
(click)="filterData('vicihumidity')">
|
||||
Kelembaban Udara
|
||||
</button>
|
||||
<button
|
||||
[ngClass]="{'active': activeButton === 'viciluminosity'}"
|
||||
(click)="filterData('viciluminosity')">
|
||||
Intensitas Cahaya
|
||||
</button>
|
||||
</div>
|
||||
<ng-container *ngIf="isLoadingDHT; else dhtData">
|
||||
<div class="d-flex align-items-center" style="padding: 50px 0px 50px 0px">
|
||||
<i class="fa fa-spinner fa-spin"></i>
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@
|
|||
.title {
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
margin: 18px 0px 0px 0px;
|
||||
margin: 18px 0px 18px 0px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
|
@ -90,6 +90,18 @@
|
|||
font-size: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button-param {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 344px) {
|
||||
|
|
@ -109,6 +121,17 @@
|
|||
font-size: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.button-param {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 80%;
|
||||
max-width: 300px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
|
|
@ -128,4 +151,28 @@
|
|||
font-size: 18px;
|
||||
}
|
||||
|
||||
.button-param {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin: 10px 0 10px 0px;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: 'Onest', sans-serif;
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
background-color: #E5E5E5;
|
||||
color: #16423C;
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
button.active {
|
||||
background-color: #16423C;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Component, OnInit, ElementRef, ViewChild, AfterViewInit, OnDestroy, OnChanges, Input, SimpleChanges, ChangeDetectorRef } from '@angular/core';
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
import { Chart, registerables, Tooltip } from 'chart.js';
|
||||
import { SensorService } from '../../../../cores/services/sensor.service';
|
||||
import { ApiResponse, ParameterSensor } from '../../../../cores/interface/sensor-data';
|
||||
import { CommonModule, formatDate } from '@angular/common';
|
||||
|
|
@ -52,6 +52,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
isNoDataNPK2: boolean = false;
|
||||
|
||||
allNoData: boolean = false;
|
||||
activeButton: string = 'vicitemperature';
|
||||
|
||||
sensorParameters: { [key: string]: string[] } = {
|
||||
dht: ['vicitemperature', 'vicihumidity', 'viciluminosity'],
|
||||
|
|
@ -162,7 +163,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
const dEnd = endDate ? this.formatDate(endDate) : this.getDate();
|
||||
|
||||
if (timeRange === 'HOURLY') {
|
||||
this.sensorService.getSensorDataHourly('dht', 'npk', hStart, hEnd, timeRange).subscribe({
|
||||
this.sensorService.getSensorDataHourly('dht', '', hStart, hEnd, timeRange).subscribe({
|
||||
next: (response) => {
|
||||
this.isLoadingDHT = false;
|
||||
if (response.statusCode === 200 && response.data.dht?.length > 0) {
|
||||
|
|
@ -280,7 +281,6 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
|
||||
updateCharts(): void {
|
||||
const interval = this.selectedInterval;
|
||||
|
||||
Object.keys(this.charts).forEach(key => {
|
||||
if (this.charts[key]) {
|
||||
this.charts[key]?.destroy();
|
||||
|
|
@ -298,6 +298,23 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
this.fetchNPK1Data(interval);
|
||||
this.fetchNPK2Data(interval);
|
||||
}
|
||||
|
||||
if (this.charts['dht']) {
|
||||
this.filterData(this.activeButton);
|
||||
}
|
||||
}
|
||||
|
||||
filterData(parameter: string): void {
|
||||
this.activeButton = parameter;
|
||||
const chart = this.charts['dht'];
|
||||
|
||||
if (chart) {
|
||||
chart.data.datasets.forEach((dataset: any) => {
|
||||
dataset.hidden = dataset.label !== this.parameterDisplayNames[parameter];
|
||||
});
|
||||
|
||||
chart.update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -327,6 +344,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
|
||||
const pointRadius = data.length === 1 ? 5 : 0;
|
||||
const pointHoverRadius = data.length === 1 ? 7 : 0;
|
||||
const isHidden = parameter !== this.activeButton;
|
||||
|
||||
return {
|
||||
label: displayName,
|
||||
|
|
@ -338,6 +356,7 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
tension: 0.5,
|
||||
pointRadius,
|
||||
pointHoverRadius,
|
||||
hidden : isHidden
|
||||
};
|
||||
}).filter(dataset => dataset !== null);
|
||||
} else {
|
||||
|
|
@ -372,7 +391,6 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
|
||||
const pointRadius = data.length === 1 ? 5 : 0;
|
||||
const pointHoverRadius = data.length === 1 ? 7 : 0;
|
||||
|
||||
return {
|
||||
label: displayName,
|
||||
data,
|
||||
|
|
@ -397,47 +415,93 @@ export class GraphComponent implements OnInit, AfterViewInit, OnDestroy, OnChang
|
|||
this.charts[sensor]?.destroy();
|
||||
}
|
||||
|
||||
|
||||
this.charts[sensor] = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: this.getLabels(response, sensor),
|
||||
datasets,
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 2,
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
mode: 'nearest',
|
||||
intersect: false,
|
||||
callbacks: {
|
||||
label: (tooltipItem: any) => {
|
||||
const paramLabel = tooltipItem.dataset.label;
|
||||
const value = tooltipItem.formattedValue;
|
||||
return `${paramLabel}: ${value}`;
|
||||
}
|
||||
}
|
||||
if(sensor === 'dht'){
|
||||
this.charts[sensor] = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: this.getLabels(response, sensor),
|
||||
datasets,
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 2,
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
mode: 'nearest',
|
||||
intersect: false,
|
||||
callbacks: {
|
||||
label: (tooltipItem: any) => {
|
||||
const paramLabel = tooltipItem.dataset.label;
|
||||
const value = tooltipItem.formattedValue;
|
||||
return `${paramLabel}: ${value}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
legend: { display: true }
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: { display: false },
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: (value: string | number, index: number, values: any) => {
|
||||
const labels = this.getLabels(response, sensor);
|
||||
return labels[index] || value;
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: { display: false },
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: (value: string | number, index: number, values: any) => {
|
||||
const labels = this.getLabels(response, sensor);
|
||||
return labels[index] || value;
|
||||
}
|
||||
}
|
||||
},
|
||||
y: { grid: { display: false }, beginAtZero: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
}else if(sensor === 'npk1' || sensor === 'npk2'){
|
||||
this.charts[sensor] = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: this.getLabels(response, sensor),
|
||||
datasets,
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 2,
|
||||
plugins: {
|
||||
tooltip: {
|
||||
enabled: true,
|
||||
mode: 'nearest',
|
||||
intersect: false,
|
||||
callbacks: {
|
||||
label: (tooltipItem: any) => {
|
||||
const paramLabel = tooltipItem.dataset.label;
|
||||
const value = tooltipItem.formattedValue;
|
||||
return `${paramLabel}: ${value}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
display: true,
|
||||
},
|
||||
y: { grid: { display: false }, beginAtZero: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
grid: { display: false },
|
||||
beginAtZero: true,
|
||||
ticks: {
|
||||
callback: (value: string | number, index: number, values: any) => {
|
||||
const labels = this.getLabels(response, sensor);
|
||||
return labels[index] || value;
|
||||
}
|
||||
}
|
||||
},
|
||||
y: { grid: { display: false }, beginAtZero: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="text-center-copyright">
|
||||
<div>©2024</div>
|
||||
<div>©2024 Agrilink</div>
|
||||
<div>Powered by <strong>Politeknik Negeri Malang</strong></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user