This commit is contained in:
kleponijo 2026-04-16 17:12:35 +07:00
parent 2d1ccdb8b2
commit 828645da5b
5 changed files with 83 additions and 10 deletions

View File

@ -34,10 +34,20 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
_repository.getSensorStream(
'anemometer/realtime', (json) => MyWindSpeed.fromJson(json)),
onData: (data) {
// Mengambil list lama dan menambah data baru untuk grafik
// 1. Ambil list kecepatan yang ada saat ini di state
final updatedSpeeds = List<double>.from(state.dailySpeeds);
// 2. Tentukan di index mana data ini harus masuk (misal berdasarkan menit saat ini)
final int index = DateTime.now().minute;
// 3. Update nilai di index tersebut
if (index < updatedSpeeds.length) {
updatedSpeeds[index] = data.speed;
}
return state.copyWith(
currentSpeed: data.speed,
dailySpeeds: updatedSpeeds,
isLoading: false,
);
},
@ -76,16 +86,22 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
List<double> _mapHistoryToDaily(List<MyWindSpeed> history) {
// Buat list 24 angka nol (representasi jam 00:00 - 23:00)
List<double> slots = List.generate(24, (_) => 0.0);
List<double> slots = List.generate(24, (_) => 0.0); // mode asli
// Kita buat 60 slot (representasi menit 0-59) agar tiap menit kelihatan titik baru
// List<double> slots = List.generate(60, (_) => 0.0); // mode percobaan
for (var item in history) {
// Ubah timestamp UTC ke jam lokal
DateTime date = item.timestamp;
DateTime date = item.timestamp; // sudah dateTime dari model
// Jika data ini adalah data hari ini, masukkan ke slot jamnya
if (date.day == DateTime.now().day) {
slots[date.hour] = item.speed;
}
} // mode asli
// pakai menit untuk percobaan (date.minute) sebagai index supaya kelihatan pergerakannya
// if (date.day == DateTime.now().day) {
// slots[date.minute] = item.speed;
// } // mode percobaan/testing
}
return slots;
}

View File

@ -1,16 +1,19 @@
/// === File ini khusus untuk urusan Grafik === ///
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
// import 'package:intl/intl.dart';
class WindSpeedChartWidget extends StatelessWidget {
final List<double> dailySpeeds;
final String period; // menambahkan parameter periode
const WindSpeedChartWidget({super.key, required this.dailySpeeds});
const WindSpeedChartWidget(
{super.key, required this.dailySpeeds, required this.period});
@override
Widget build(BuildContext context) {
return Container(
height: 250,
height: 270,
padding: const EdgeInsets.fromLTRB(10, 20, 20, 10),
decoration: BoxDecoration(
color: Colors.white,
@ -25,9 +28,37 @@ class WindSpeedChartWidget extends StatelessWidget {
),
child: LineChart(
LineChartData(
minY: 0,
maxY: 50,
gridData: const FlGridData(show: false),
titlesData: const FlTitlesData(show: false),
borderData: FlBorderData(show: false),
// === PENGATURAN LABEL SUMBU X ===
titlesData: FlTitlesData(
show: true,
rightTitles:
const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles:
const AxisTitles(sideTitles: SideTitles(showTitles: false)),
leftTitles:
const AxisTitles(sideTitles: SideTitles(showTitles: false)),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 30,
interval:
_getInterval(), // Mengatur jarak label agar tidak tumpang tindih
getTitlesWidget: (value, meta) {
return SideTitleWidget(
meta: meta,
space: 8,
child: Text(
_getBottomTitle(value),
style: const TextStyle(
color: Colors.grey, fontSize: 10),
),
);
}))),
lineBarsData: [
LineChartBarData(
spots: dailySpeeds.asMap().entries.map((e) {
@ -55,4 +86,27 @@ class WindSpeedChartWidget extends StatelessWidget {
),
);
}
// Logika untuk menentukan teks label di bawah
String _getBottomTitle(double value) {
int index = value.toInt();
if (index < 0 || index >= dailySpeeds.length) return '';
if (period == "Hari Ini") {
// Tampilkan jam genap saja (0, 2, 4...) agar tidak penuh
return index % 4 == 0 ? "${index.toString().padLeft(2, '0')}:00" : "";
} else if (period == "Minggu Ini") {
const days = ["Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Min"];
return days[index % 7];
} else {
// Bulanan: Tampilkan tanggal kelipatan 5
return (index + 1) % 5 == 0 ? "${index + 1}" : "";
}
}
double _getInterval() {
if (period == "Hari Ini") return 1; // Cek tiap jam
if (period == "Minggu Ini") return 1; // Cek tiap hari
return 1;
}
}

View File

@ -45,7 +45,10 @@ class WindSpeedScreen extends StatelessWidget {
const PeriodSelector(),
const SizedBox(height: 15),
WindSpeedChartWidget(dailySpeeds: state.dailySpeeds),
WindSpeedChartWidget(
dailySpeeds: state.dailySpeeds,
period: state.selectedPeriod,
),
const SizedBox(height: 30),

View File

@ -20,7 +20,7 @@ class MyWindSpeed {
speed: (json['speed'] ?? 0).toDouble(),
pulse: (json['pulse'] ?? 0) as int,
timestamp: DateTime.fromMillisecondsSinceEpoch(
(json['timestamp'] ?? 0) * 1000, // kalau dari Unix detik
(json['timesTamp'] ?? 0) * 1000, // kalau dari Unix detik
).toLocal(),
);
}

View File

@ -1,4 +1,4 @@
import 'models/models.dart';
// import 'models/models.dart';
abstract class MonitoringRepository {
// fungsi untuk ambil data berkali/streaming