Skip to content
Merged
41 changes: 41 additions & 0 deletions lib/providers/gyroscope_state_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ 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';
import 'package:intl/intl.dart';

class GyroscopeProvider extends ChangeNotifier {
StreamSubscription<GyroscopeEvent>? _gyroscopeSubscription;
Expand All @@ -22,6 +23,9 @@ class GyroscopeProvider extends ChangeNotifier {
double _yMin = 0, _yMax = 0;
double _zMin = 0, _zMax = 0;

bool _isRecording = false;
List<List<dynamic>> _recordedData = [];

double get xValue => _gyroscopeEvent.x;
double get yValue => _gyroscopeEvent.y;
double get zValue => _gyroscopeEvent.z;
Expand All @@ -34,6 +38,7 @@ class GyroscopeProvider extends ChangeNotifier {
double get zMax => _zMax;

bool get isListening => _gyroscopeSubscription != null;
bool get isRecording => _isRecording;

void initializeSensors() {
if (_gyroscopeSubscription != null) return;
Expand Down Expand Up @@ -61,6 +66,20 @@ class GyroscopeProvider extends ChangeNotifier {
final y = _gyroscopeEvent.y;
final z = _gyroscopeEvent.z;

if (_isRecording) {
final now = DateTime.now();
final dateFormat = DateFormat('yyyy-MM-dd HH:mm:ss.SSS');
_recordedData.add([
now.millisecondsSinceEpoch.toString(),
dateFormat.format(now),
x.toStringAsFixed(6),
y.toStringAsFixed(6),
z.toStringAsFixed(6),
0,
0
]);
}

_xData.add(x);
_yData.add(y);
_zData.add(z);
Expand Down Expand Up @@ -88,6 +107,28 @@ class GyroscopeProvider extends ChangeNotifier {
notifyListeners();
}

void startRecording() {
_isRecording = true;
_recordedData = [
[
'Timestamp',
'DateTime',
'ReadingsX',
'ReadingsY',
'ReadingsZ',
'Latitude',
'Longitude'
]
];
notifyListeners();
}

List<List<dynamic>> stopRecording() {
_isRecording = false;
notifyListeners();
return _recordedData;
}

List<FlSpot> getAxisData(String axis) {
switch (axis) {
case 'x':
Expand Down
8 changes: 5 additions & 3 deletions lib/view/compass_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -180,15 +180,17 @@ class _CompassScreenContentState extends State<CompassScreenContent> {
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Radio<String>(
value: axis,
RadioGroup(
groupValue: compassProvider.selectedAxis,
onChanged: (String? value) {
if (value != null) {
compassProvider.onAxisSelected(value);
}
},
activeColor: radioButtonActiveColor,
child: Radio<String>(
value: axis,
activeColor: radioButtonActiveColor,
),
),
Text(
label,
Expand Down
181 changes: 150 additions & 31 deletions lib/view/gyroscope_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import 'package:pslab/view/widgets/gyroscope_card.dart';
import 'package:pslab/view/widgets/common_scaffold_widget.dart';
import 'package:pslab/l10n/app_localizations.dart';
import 'package:pslab/providers/locator.dart';
import 'package:pslab/others/csv_service.dart';
import 'package:pslab/view/logged_data_screen.dart';
import '../theme/colors.dart';
import '../constants.dart';
import 'gyroscope_config_screen.dart';

class GyroscopeScreen extends StatefulWidget {
Expand All @@ -21,6 +24,27 @@ class _GyroscopeScreenState extends State<GyroscopeScreen> {
AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
bool _showGuide = false;
static const imagePath = 'assets/images/gyroscope_axes_orientation.png';
final CsvService _csvService = CsvService();
late GyroscopeProvider _provider;

@override
void initState() {
super.initState();
_provider = GyroscopeProvider();
WidgetsBinding.instance.addPostFrameCallback((_) {
if (mounted) {
_provider.initializeSensors();
}
});
}

@override
void dispose() {
_provider.disposeSensors();
_provider.dispose();
super.dispose();
}

void _showInstrumentGuide() {
setState(() {
_showGuide = true;
Expand Down Expand Up @@ -72,7 +96,7 @@ class _GyroscopeScreenState extends State<GyroscopeScreen> {
if (value != null) {
switch (value) {
case 'show_logged_data':
// TODO
_navigateToLoggedData();
break;
case 'gyroscope_config':
_navigateToConfig();
Expand All @@ -82,6 +106,19 @@ class _GyroscopeScreenState extends State<GyroscopeScreen> {
});
}

Future<void> _navigateToLoggedData() async {
await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => LoggedDataScreen(
instrumentName: 'gyroscope',
appBarName: 'Gyroscope',
instrumentIcon: instrumentIcons[10],
),
),
);
}

void _navigateToConfig() {
Navigator.push(
context,
Expand All @@ -93,40 +130,122 @@ class _GyroscopeScreenState extends State<GyroscopeScreen> {
));
}

Future<void> _toggleRecording() async {
if (_provider.isRecording) {
final data = _provider.stopRecording();
await _showSaveFileDialog(data);
} else {
_provider.startRecording();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'${appLocalizations.recordingStarted}...',
style: TextStyle(color: snackBarContentColor),
),
backgroundColor: snackBarBackgroundColor,
),
);
}
}

Future<void> _showSaveFileDialog(List<List<dynamic>> data) async {
final TextEditingController filenameController = TextEditingController();
final String defaultFilename = '';
filenameController.text = defaultFilename;

final String? fileName = await showDialog<String>(
context: context,
builder: (context) {
return AlertDialog(
title: Text(appLocalizations.saveRecording),
content: TextField(
controller: filenameController,
decoration: InputDecoration(
hintText: appLocalizations.enterFileName,
labelText: appLocalizations.fileName,
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: Text(appLocalizations.cancel.toUpperCase()),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context, filenameController.text);
},
child: Text(appLocalizations.save),
),
],
);
},
);

if (fileName != null) {
_csvService.writeMetaData('gyroscope', data);
final file = await _csvService.saveCsvFile('gyroscope', fileName, data);
if (mounted) {
if (file != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'${appLocalizations.fileSaved}: ${file.path.split('/').last}',
style: TextStyle(color: snackBarContentColor),
),
backgroundColor: snackBarBackgroundColor,
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
appLocalizations.failedToSave,
style: TextStyle(color: snackBarContentColor),
),
backgroundColor: snackBarBackgroundColor,
),
);
}
}
}
}

@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<GyroscopeProvider>(
create: (_) => GyroscopeProvider()..initializeSensors(),
),
],
return ChangeNotifierProvider<GyroscopeProvider>.value(
value: _provider,
child: Stack(children: [
CommonScaffold(
title: appLocalizations.gyroscopeTitle,
onGuidePressed: _showInstrumentGuide,
onOptionsPressed: _showOptionsMenu,
body: SafeArea(
child: Column(
children: [
Expanded(
child: GyroscopeCard(
color: xOrientationChartLineColor,
axis: appLocalizations.xAxis),
Consumer<GyroscopeProvider>(
builder: (context, provider, child) {
return CommonScaffold(
title: appLocalizations.gyroscopeTitle,
onGuidePressed: _showInstrumentGuide,
onOptionsPressed: _showOptionsMenu,
onRecordPressed: _toggleRecording,
isRecording: provider.isRecording,
body: SafeArea(
child: Column(
children: [
Expanded(
child: GyroscopeCard(
color: xOrientationChartLineColor,
axis: appLocalizations.xAxis),
),
Expanded(
child: GyroscopeCard(
color: yOrientationChartLineColor,
axis: appLocalizations.yAxis),
),
Expanded(
child: GyroscopeCard(
color: zOrientationChartLineColor,
axis: appLocalizations.zAxis),
),
],
),
Expanded(
child: GyroscopeCard(
color: yOrientationChartLineColor,
axis: appLocalizations.yAxis),
),
Expanded(
child: GyroscopeCard(
color: zOrientationChartLineColor,
axis: appLocalizations.zAxis),
),
],
),
),
),
);
},
),
if (_showGuide)
InstrumentOverviewDrawer(
Expand Down
Loading
Loading