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

135 lines
3.8 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.minY,
required this.maxY,
required this.sampleTimeMicross});
final String title;
final double aspectRatio;
final double maxTimeSeconds;
final Future<double> Function() readAnalog;
final int sampleTimeMicross;
final double minY;
final double maxY;
@override
State<StatefulWidget> createState() => _Plot();
}
class _Plot extends State<Plot> {
late Timer timer;
late int limit= ((widget.maxTimeSeconds)/(widget.sampleTimeMicross/1000)).toInt();
late List<FlSpot> adc = <FlSpot>[const FlSpot( 0, 0)];
int index = 0;
double el = 0.0;
double valPrev = 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(microseconds: widget.sampleTimeMicross), (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.sampleTimeMicross)/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: widget.minY,
maxY: widget.maxY,
// minY: -0.5,
// maxY: 0.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)));
}
}