Skip to content

Commit 413451d

Browse files
Yugesh-Kumar-SmarcnauseCloudyPadmal
authored
feat: ported barometer instrument (#2743)
Co-authored-by: Marc Nause <[email protected]> Co-authored-by: Padmal <[email protected]>
1 parent e499cd6 commit 413451d

File tree

7 files changed

+627
-6
lines changed

7 files changed

+627
-6
lines changed

lib/constants.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ String lx = 'Lx';
256256
String maxScaleError = 'Max Scale';
257257
String lightSensorError = 'Light sensor error:';
258258
String lightSensorInitialError = 'Failed to initialize light sensor:';
259+
String barometerTitle = 'Barometer';
260+
String atm = 'atm';
261+
String barometerSensorInitialError = 'Failed to initialize barometer sensor:';
262+
String barometerSensorError = 'Barometer sensor error occurred';
263+
String barometerNotAvailable = 'Barometer sensor not available on this device';
264+
String meterUnit = 'm';
265+
String altitudeLabel = 'Altitude';
259266
String soundMeterError = 'Sound sensor error:';
260267
String soundMeterInitialError = 'Sound sensor initialization error:';
261268
String db = 'dB';

lib/main.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
33
import 'package:pslab/providers/board_state_provider.dart';
44
import 'package:pslab/providers/locator.dart';
55
import 'package:pslab/view/accelerometer_screen.dart';
6+
import 'package:pslab/view/barometer_screen.dart';
67
import 'package:pslab/view/connect_device_screen.dart';
78
import 'package:pslab/view/faq_screen.dart';
89
import 'package:pslab/view/gyroscope_screen.dart';
@@ -59,6 +60,7 @@ class MyApp extends StatelessWidget {
5960
'/gyroscope': (context) => const GyroscopeScreen(),
6061
'/roboticArm': (context) => const RoboticArmScreen(),
6162
'/luxmeter': (context) => const LuxMeterScreen(),
63+
'/barometer': (context) => const BarometerScreen(),
6264
'/soundmeter': (context) => const SoundMeterScreen(),
6365
},
6466
);
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import 'dart:async';
2+
import 'dart:math';
3+
import 'package:fl_chart/fl_chart.dart';
4+
import 'package:flutter/material.dart';
5+
import 'package:pslab/others/logger_service.dart';
6+
import 'package:sensors_plus/sensors_plus.dart';
7+
import 'package:flutter/foundation.dart';
8+
import 'package:pslab/constants.dart';
9+
10+
class BarometerStateProvider extends ChangeNotifier {
11+
double _currentPressure = 0.0;
12+
StreamSubscription? _barometerSubscription;
13+
Timer? _timeTimer;
14+
final List<double> _pressureData = [];
15+
final List<double> _timeData = [];
16+
final List<FlSpot> pressureChartData = [];
17+
double _startTime = 0;
18+
double _currentTime = 0;
19+
final int _maxLength = 50;
20+
double _pressureMin = 0;
21+
double _pressureMax = 0;
22+
double _pressureSum = 0;
23+
int _dataCount = 0;
24+
bool _sensorAvailable = false;
25+
26+
Function(String)? onSensorError;
27+
28+
void initializeSensors({Function(String)? onError}) {
29+
onSensorError = onError;
30+
31+
try {
32+
_startTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
33+
_timeTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
34+
_currentTime =
35+
(DateTime.now().millisecondsSinceEpoch / 1000.0) - _startTime;
36+
if (_sensorAvailable) {
37+
_updateData();
38+
}
39+
notifyListeners();
40+
});
41+
42+
Timer sensorTimeout = Timer(const Duration(seconds: 3), () {
43+
if (!_sensorAvailable) {
44+
_handleSensorError(barometerSensorError);
45+
}
46+
});
47+
48+
_barometerSubscription = barometerEventStream().listen(
49+
(BarometerEvent event) {
50+
_currentPressure = event.pressure / 1013.25;
51+
if (!_sensorAvailable) {
52+
_sensorAvailable = true;
53+
sensorTimeout.cancel();
54+
}
55+
notifyListeners();
56+
},
57+
onError: (error) {
58+
logger.e("$barometerSensorError $error");
59+
sensorTimeout.cancel();
60+
_handleSensorError(error);
61+
},
62+
cancelOnError: false,
63+
);
64+
} catch (e) {
65+
logger.e("$barometerSensorInitialError $e");
66+
_handleSensorError(e);
67+
}
68+
}
69+
70+
void _handleSensorError(dynamic error) {
71+
_sensorAvailable = false;
72+
onSensorError?.call(barometerNotAvailable);
73+
logger.e("$barometerSensorError $error");
74+
}
75+
76+
void disposeSensors() {
77+
_barometerSubscription?.cancel();
78+
_timeTimer?.cancel();
79+
}
80+
81+
@override
82+
void dispose() {
83+
disposeSensors();
84+
super.dispose();
85+
}
86+
87+
void _updateData() {
88+
if (!_sensorAvailable) return;
89+
90+
final pressure = _currentPressure;
91+
final time = _currentTime;
92+
_pressureData.add(pressure);
93+
_timeData.add(time);
94+
_pressureSum += pressure;
95+
_dataCount++;
96+
if (_pressureData.length > _maxLength) {
97+
final removedValue = _pressureData.removeAt(0);
98+
_timeData.removeAt(0);
99+
_pressureSum -= removedValue;
100+
_dataCount--;
101+
}
102+
if (_pressureData.isNotEmpty) {
103+
_pressureMin = _pressureData.reduce(min);
104+
_pressureMax = _pressureData.reduce(max);
105+
}
106+
pressureChartData.clear();
107+
for (int i = 0; i < _pressureData.length; i++) {
108+
pressureChartData.add(FlSpot(_timeData[i], _pressureData[i]));
109+
}
110+
notifyListeners();
111+
}
112+
113+
double _pressureToAltitude(double pressureAtm) {
114+
const double seaLevelPressureAtm = 1.0;
115+
const double temperatureK = 288.15;
116+
const double lapseRate = 0.0065;
117+
const double gasConstant = 287.05;
118+
const double gravity = 9.80665;
119+
120+
if (pressureAtm <= 0) return 0.0;
121+
122+
double altitude = (temperatureK / lapseRate) *
123+
(1 -
124+
pow(pressureAtm / seaLevelPressureAtm,
125+
(gasConstant * lapseRate) / gravity));
126+
127+
return altitude;
128+
}
129+
130+
double getCurrentPressure() => _currentPressure;
131+
double getMinPressure() => _pressureMin;
132+
double getMaxPressure() => _pressureMax;
133+
double getAveragePressure() =>
134+
_dataCount > 0 ? _pressureSum / _dataCount : 0.0;
135+
136+
double getCurrentAltitude() => _pressureToAltitude(_currentPressure);
137+
double getMinAltitude() =>
138+
_pressureMin > 0 ? _pressureToAltitude(_pressureMin) : 0.0;
139+
double getMaxAltitude() =>
140+
_pressureMax > 0 ? _pressureToAltitude(_pressureMax) : 0.0;
141+
double getAverageAltitude() => _pressureToAltitude(getAveragePressure());
142+
143+
double getMaxAltitudeForChart() =>
144+
_pressureMax > 0 ? _pressureToAltitude(0) : 10000.0;
145+
double getMinAltitudeForChart() =>
146+
_pressureMin > 0 ? _pressureToAltitude(_pressureMax * 1.1) : 0.0;
147+
double getAltitudeInterval() {
148+
double maxAlt = getMaxAltitudeForChart();
149+
return maxAlt > 0 ? (maxAlt / 5) : 2000;
150+
}
151+
152+
List<FlSpot> getPressureChartData() => pressureChartData;
153+
int getDataLength() => pressureChartData.length;
154+
double getCurrentTime() => _currentTime;
155+
double getMaxTime() => _timeData.isNotEmpty ? _timeData.last : 0;
156+
double getMinTime() => _timeData.isNotEmpty ? _timeData.first : 0;
157+
double getTimeInterval() {
158+
if (_currentTime <= 10) return 2;
159+
if (_currentTime <= 30) return 5;
160+
return 10;
161+
}
162+
163+
bool get sensorAvailable => _sensorAvailable;
164+
}

0 commit comments

Comments
 (0)