Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,6 @@ String timeAxisLabel = 'Time(s)';
String accelerationAxisLabel = 'm/s²';
String minValue = 'Min: ';
String maxValue = 'Max: ';
String gyroscopeTitle = "Gyroscope";
String gyroscopeAxisLabel = 'rad/s';
String noData = 'No data available';
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:pslab/providers/locator.dart';
import 'package:pslab/view/accelerometer_screen.dart';
import 'package:pslab/view/connect_device_screen.dart';
import 'package:pslab/view/faq_screen.dart';
import 'package:pslab/view/gyroscope_screen.dart';
import 'package:pslab/view/instruments_screen.dart';
import 'package:pslab/view/oscilloscope_screen.dart';
import 'package:pslab/view/settings_screen.dart';
Expand Down Expand Up @@ -51,6 +52,7 @@ class MyApp extends StatelessWidget {
'/aboutUs': (context) => const AboutUsScreen(),
'/softwareLicenses': (context) => const SoftwareLicensesScreen(),
'/accelerometer': (context) => const AccelerometerScreen(),
'/gyroscope': (context) => const GyroscopeScreen(),
},
);
}
Expand Down
161 changes: 161 additions & 0 deletions lib/providers/gyroscope_state_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import 'dart:async';
import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/foundation.dart';
import 'package:sensors_plus/sensors_plus.dart';
import 'package:pslab/others/logger_service.dart';

class GyroscopeProvider extends ChangeNotifier {
StreamSubscription<GyroscopeEvent>? _gyroscopeSubscription;
GyroscopeEvent _gyroscopeEvent = GyroscopeEvent(0, 0, 0, DateTime.now());

final List<double> _xData = [];
final List<double> _yData = [];
final List<double> _zData = [];

final List<FlSpot> xData = [];
final List<FlSpot> yData = [];
final List<FlSpot> zData = [];

final int _maxLength = 50;
double _xMin = 0, _xMax = 0;
double _yMin = 0, _yMax = 0;
double _zMin = 0, _zMax = 0;

double get xValue => _gyroscopeEvent.x;
double get yValue => _gyroscopeEvent.y;
double get zValue => _gyroscopeEvent.z;

double get xMin => _xMin;
double get xMax => _xMax;
double get yMin => _yMin;
double get yMax => _yMax;
double get zMin => _zMin;
double get zMax => _zMax;

bool get isListening => _gyroscopeSubscription != null;

void initializeSensors() {
if (_gyroscopeSubscription != null) return;

_gyroscopeSubscription = gyroscopeEventStream().listen(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Throttle sensor update frequency

Consider throttling or sampling the sensor event stream to reduce unnecessary listener rebuilds and improve performance.

Suggested implementation:

  // Add import at the top of the file:
  // import 'package:rxdart/rxdart.dart';

  void initializeSensors() {
    if (_gyroscopeSubscription != null) return;

    _gyroscopeSubscription = gyroscopeEventStream()
        .throttleTime(const Duration(milliseconds: 50))
        .listen(
      (event) {
        _gyroscopeEvent = event;
        _updateData();
        notifyListeners();
      },
      onError: (error) {
        logger.e("Gyroscope error: $error");
      },
      cancelOnError: true,
    );
  }

  • Add import 'package:rxdart/rxdart.dart'; at the top of the file if not already present.
  • Ensure rxdart is included in your pubspec.yaml dependencies.
  • Adjust the throttle duration as needed for your use case.

(event) {
_gyroscopeEvent = event;
_updateData();
notifyListeners();
Comment on lines +44 to +45
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Duplicate notifyListeners call

Consider removing one of the notifyListeners calls to prevent unnecessary rebuilds.

},
onError: (error) {
logger.e("Gyroscope error: $error");
},
cancelOnError: true,
);
}

void disposeSensors() {
_gyroscopeSubscription?.cancel();
_gyroscopeSubscription = null;
}

void _updateData() {
final x = _gyroscopeEvent.x;
final y = _gyroscopeEvent.y;
final z = _gyroscopeEvent.z;

_xData.add(x);
_yData.add(y);
_zData.add(z);

if (_xData.length > _maxLength) _xData.removeAt(0);
if (_yData.length > _maxLength) _yData.removeAt(0);
if (_zData.length > _maxLength) _zData.removeAt(0);

_xMin = _xData.reduce(min);
_xMax = _xData.reduce(max);
_yMin = _yData.reduce(min);
_yMax = _yData.reduce(max);
_zMin = _zData.reduce(min);
_zMax = _zData.reduce(max);

xData.clear();
yData.clear();
zData.clear();

for (int i = 0; i < _xData.length; i++) {
xData.add(FlSpot(i.toDouble(), _xData[i]));
yData.add(FlSpot(i.toDouble(), _yData[i]));
zData.add(FlSpot(i.toDouble(), _zData[i]));
}
notifyListeners();
}

List<FlSpot> getAxisData(String axis) {
switch (axis) {
case 'x':
return xData;
case 'y':
return yData;
case 'z':
return zData;
default:
return [];
}
}

double getMin(String axis) {
switch (axis) {
case 'x':
return _xMin;
case 'y':
return _yMin;
case 'z':
return _zMin;
default:
return 0.0;
}
}

double getMax(String axis) {
switch (axis) {
case 'x':
return _xMax;
case 'y':
return _yMax;
case 'z':
return _zMax;
default:
return 0.0;
}
}

double getCurrent(String axis) {
switch (axis) {
case 'x':
return _gyroscopeEvent.x;
case 'y':
return _gyroscopeEvent.y;
case 'z':
return _gyroscopeEvent.z;
default:
return 0.0;
}
}

int getDataLength(String axis) {
switch (axis) {
case 'x':
return xData.length;
case 'y':
return yData.length;
case 'z':
return zData.length;
default:
return 0;
}
}

@override
void dispose() {
disposeSensors();
super.dispose();
}
}
44 changes: 44 additions & 0 deletions lib/view/gyroscope_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:pslab/providers/gyroscope_state_provider.dart';
import 'package:pslab/constants.dart';
import 'package:pslab/view/widgets/gyroscope_card.dart';
import 'package:pslab/view/widgets/common_scaffold_widget.dart';

class GyroscopeScreen extends StatefulWidget {
const GyroscopeScreen({super.key});

@override
State<StatefulWidget> createState() => _GyroscopeScreenState();
}

class _GyroscopeScreenState extends State<GyroscopeScreen> {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<GyroscopeProvider>(
create: (_) => GyroscopeProvider()..initializeSensors(),
),
],
child: CommonScaffold(
title: gyroscopeTitle,
body: SafeArea(
child: Column(
children: [
Expanded(
child: GyroscopeCard(color: Colors.yellow, axis: xAxis),
),
Expanded(
child: GyroscopeCard(color: Colors.purple, axis: yAxis),
),
Expanded(
child: GyroscopeCard(color: Colors.green, axis: zAxis),
),
],
),
),
),
);
}
}
12 changes: 12 additions & 0 deletions lib/view/instruments_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ class _InstrumentsScreenState extends State<InstrumentsScreen> {
);
}
break;
case 10:
if (Navigator.canPop(context) &&
ModalRoute.of(context)?.settings.name == '/gyroscope') {
Navigator.popUntil(context, ModalRoute.withName('/gyroscope'));
} else {
Navigator.pushNamedAndRemoveUntil(
context,
'/gyroscope',
(route) => route.isFirst,
);
}
break;
default:
break;
}
Expand Down
Loading