HeartBeatRate/Software/dashboard/lib/ui/plot.dart

128 lines
3.6 KiB
Dart

import 'dart:async';
import 'dart:core';
import 'dart:math' as math;
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
class Plot extends StatefulWidget {
const Plot({
super.key,
required this.title,
required this.aspectRatio,
required this.maxTimeSeconds,
required this.readAnalog,
required this.sampleTimeMillis});
final String title;
final double aspectRatio;
final int maxTimeSeconds;
final Future<double> Function() readAnalog;
final int sampleTimeMillis;
@override
State<StatefulWidget> createState() => _Plot();
}
class _Plot extends State<Plot> {
late Timer timer;
late int limit= ((widget.maxTimeSeconds)/(widget.sampleTimeMillis/1000)).toInt();
late List<FlSpot> adc = <FlSpot>[];
int index = 0;
double el = 0.0;
late Logger log;
@override
void dispose() {
super.dispose();
timer.cancel();
}
@override
void initState() {
super.initState();
log = Logger("Plot : ${widget.title}");
log.info('limit : $limit');
timer = Timer.periodic(Duration(milliseconds: widget.sampleTimeMillis), (timer) {
widget.readAnalog().then((val){
if (index>=limit) {
log.info('================================================================ reset $index : $el : ${index != 0 ? adc[index-1] : 0}');
index = 0;
el = 0.0;
adc.clear();
}
setState(() {
el = (index * widget.sampleTimeMillis)/1000;
adc.add(FlSpot( el, val));
log.info('================================================================ $index : $el : ${adc[index]}');
index +=1;
});
});
});
}
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: widget.aspectRatio,
child : LineChart(
LineChartData(
minY: -5,
maxY: 5,
minX: 0,
maxX: widget.maxTimeSeconds.toDouble(),
lineBarsData: [LineChartBarData(
spots: adc,
dotData: const FlDotData(
show: false,
),
barWidth: 2,
isCurved: false,
)],
titlesData: const FlTitlesData(show: true,
rightTitles: AxisTitles(sideTitles: SideTitles(reservedSize: 40, showTitles: false)),
topTitles: AxisTitles(sideTitles: SideTitles(reservedSize: 40, showTitles: false)),
),
gridData: const FlGridData(show: true, drawVerticalLine: false),
)
)
);
}
}
class DummyData {
late int limitCount;
late List<FlSpot> sinPoints;
double xValue = 0;
double step = 0.05;
int index = 0;
late Timer timer;
late void Function() stateChange;
DummyData(){
limitCount = (20/step).toInt();
sinPoints = List<FlSpot>.generate(limitCount+1, (index) => FlSpot(index+step,0));
}
void begin(Function() sc) {
stateChange = sc;
timer = Timer.periodic(const Duration(milliseconds: 2), (timer) {
stateChange.call();
if (xValue >= 20) {
xValue = 0;
index = 0;
sinPoints.clear();
} else {
xValue += step;
index += 1;
}
// print("$index : $xValue");
});
}
void update(){
sinPoints.insert(index, FlSpot(xValue, 1 - (math.Random(xValue.toInt()).nextDouble()*2)));
}
}