Skip to content

feat: ported barometer instrument #2743

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: flutter
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,13 @@ String lx = 'Lx';
String maxScaleError = 'Max Scale';
String lightSensorError = 'Light sensor error:';
String lightSensorInitialError = 'Failed to initialize light sensor:';
String barometerTitle = 'Barometer';
String atm = 'atm';
String barometerSensorInitialError = 'Failed to initialize barometer sensor:';
String barometerSensorError = 'Barometer sensor error occurred';
String barometerNotAvailable = 'Barometer sensor not available on this device';
String meterUnit = 'm';
String altitudeLabel = 'Altitude';
String soundMeterError = 'Sound sensor error:';
String soundMeterInitialError = 'Sound sensor initialization error:';
String db = 'dB';
Expand Down
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
import 'package:pslab/providers/board_state_provider.dart';
import 'package:pslab/providers/locator.dart';
import 'package:pslab/view/accelerometer_screen.dart';
import 'package:pslab/view/barometer_screen.dart';
import 'package:pslab/view/connect_device_screen.dart';
import 'package:pslab/view/faq_screen.dart';
import 'package:pslab/view/gyroscope_screen.dart';
Expand Down Expand Up @@ -55,6 +56,7 @@ class MyApp extends StatelessWidget {
'/accelerometer': (context) => const AccelerometerScreen(),
'/gyroscope': (context) => const GyroscopeScreen(),
'/luxmeter': (context) => const LuxMeterScreen(),
'/barometer': (context) => const BarometerScreen(),
'/soundmeter': (context) => const SoundMeterScreen(),
},
);
Expand Down
166 changes: 166 additions & 0 deletions lib/providers/barometer_state_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import 'dart:async';
import 'dart:math';
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:pslab/others/logger_service.dart';
import 'package:sensors_plus/sensors_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:pslab/constants.dart';

class BarometerStateProvider extends ChangeNotifier {
double _currentPressure = 0.0;
StreamSubscription? _barometerSubscription;
Timer? _timeTimer;
final List<double> _pressureData = [];
final List<double> _timeData = [];
final List<FlSpot> pressureChartData = [];
double _startTime = 0;
double _currentTime = 0;
final int _maxLength = 50;
double _pressureMin = 0;
double _pressureMax = 0;
double _pressureSum = 0;
int _dataCount = 0;
bool _sensorAvailable = true;

Function(String)? onSensorError;

void initializeSensors({Function(String)? onError}) {
onSensorError = onError;

try {
_startTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
_timeTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
_currentTime =
(DateTime.now().millisecondsSinceEpoch / 1000.0) - _startTime;
if (_sensorAvailable) {
_updateData();
}
notifyListeners();
});

_barometerSubscription = barometerEventStream().listen(
(BarometerEvent event) {
_currentPressure = event.pressure / 1013.25;
_sensorAvailable = true;
notifyListeners();
},
onError: (error) {
logger.e("$barometerSensorError $error");
_handleSensorError(error);
},
cancelOnError: false,
);
} catch (e) {
logger.e("$barometerSensorInitialError $e");
_handleSensorError(e);
}
}

void _handleSensorError(dynamic error) {
_sensorAvailable = false;
String errorString = error.toString().toLowerCase();
if (errorString.contains('not available') ||
errorString.contains('not supported') ||
errorString.contains('sensor not found') ||
errorString.contains('no sensor')) {
_handleSensorNotAvailable();
} else {
onSensorError?.call(barometerSensorError);
}
}

void _handleSensorNotAvailable() {
_sensorAvailable = false;
onSensorError?.call(barometerNotAvailable);
}

void disposeSensors() {
_barometerSubscription?.cancel();
_timeTimer?.cancel();
}

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

void _updateData() {
if (!_sensorAvailable) return;

final pressure = _currentPressure;
final time = _currentTime;
_pressureData.add(pressure);
_timeData.add(time);
_pressureSum += pressure;
_dataCount++;
if (_pressureData.length > _maxLength) {
final removedValue = _pressureData.removeAt(0);
_timeData.removeAt(0);
_pressureSum -= removedValue;
_dataCount--;
}
if (_pressureData.isNotEmpty) {
_pressureMin = _pressureData.reduce(min);
_pressureMax = _pressureData.reduce(max);
}
pressureChartData.clear();
for (int i = 0; i < _pressureData.length; i++) {
pressureChartData.add(FlSpot(_timeData[i], _pressureData[i]));
}
notifyListeners();
}

double _pressureToAltitude(double pressureAtm) {
const double seaLevelPressureAtm = 1.0;
const double temperatureK = 288.15;
const double lapseRate = 0.0065;
const double gasConstant = 287.05;
const double gravity = 9.80665;

if (pressureAtm <= 0) return 0.0;

double altitude = (temperatureK / lapseRate) *
(1 -
pow(pressureAtm / seaLevelPressureAtm,
(gasConstant * lapseRate) / gravity));

return altitude;
}

double getCurrentPressure() => _currentPressure;
double getMinPressure() => _pressureMin;
double getMaxPressure() => _pressureMax;
double getAveragePressure() =>
_dataCount > 0 ? _pressureSum / _dataCount : 0.0;

double getCurrentAltitude() => _pressureToAltitude(_currentPressure);
double getMinAltitude() =>
_pressureMin > 0 ? _pressureToAltitude(_pressureMin) : 0.0;
double getMaxAltitude() =>
_pressureMax > 0 ? _pressureToAltitude(_pressureMax) : 0.0;
double getAverageAltitude() => _pressureToAltitude(getAveragePressure());

double getMaxAltitudeForChart() =>
_pressureMax > 0 ? _pressureToAltitude(0) : 10000.0;
double getMinAltitudeForChart() =>
_pressureMin > 0 ? _pressureToAltitude(_pressureMax * 1.1) : 0.0;
double getAltitudeInterval() {
double maxAlt = getMaxAltitudeForChart();
return maxAlt > 0 ? (maxAlt / 5) : 2000;
}

List<FlSpot> getPressureChartData() => pressureChartData;
int getDataLength() => pressureChartData.length;
double getCurrentTime() => _currentTime;
double getMaxTime() => _timeData.isNotEmpty ? _timeData.last : 0;
double getMinTime() => _timeData.isNotEmpty ? _timeData.first : 0;
double getTimeInterval() {
if (_currentTime <= 10) return 2;
if (_currentTime <= 30) return 5;
return 10;
}

bool get sensorAvailable => _sensorAvailable;
}
Loading