@@ -34,7 +34,15 @@ class BarometerStateProvider extends ChangeNotifier {
34
34
bool _sensorAvailable = false ;
35
35
bool _isRecording = false ;
36
36
List <List <dynamic >> _recordedData = [];
37
+ bool _isPlayingBack = false ;
38
+ List <List <dynamic >>? _playbackData;
39
+ int _playbackIndex = 0 ;
40
+ Timer ? _playbackTimer;
41
+ bool _isPlaybackPaused = false ;
42
+
37
43
bool get isRecording => _isRecording;
44
+ bool get isPlayingBack => _isPlayingBack;
45
+ bool get isPlaybackPaused => _isPlaybackPaused;
38
46
39
47
StreamSubscription ? _barometerSubscription;
40
48
@@ -46,6 +54,7 @@ class BarometerStateProvider extends ChangeNotifier {
46
54
String _currentSensorType = 'In-built Sensor' ;
47
55
48
56
Function (String )? onSensorError;
57
+ Function ? onPlaybackEnd;
49
58
50
59
BarometerStateProvider (this ._configProvider) {
51
60
_configProvider.addListener (_onConfigChanged);
@@ -232,6 +241,118 @@ class BarometerStateProvider extends ChangeNotifier {
232
241
logger.e ("${appLocalizations .barometerSensorError } $error " );
233
242
}
234
243
244
+ void startPlayback (List <List <dynamic >> data) {
245
+ if (data.length <= 1 ) return ;
246
+
247
+ _isPlayingBack = true ;
248
+ _isPlaybackPaused = false ;
249
+ _playbackData = data;
250
+ _playbackIndex = 1 ;
251
+
252
+ _timeTimer? .cancel ();
253
+ _dataTimer? .cancel ();
254
+
255
+ _pressureData.clear ();
256
+ pressureChartData.clear ();
257
+ _timeData.clear ();
258
+ _startTime = DateTime .now ().millisecondsSinceEpoch / 1000.0 ;
259
+ _currentTime = 0 ;
260
+ _pressureSum = 0 ;
261
+ _dataCount = 0 ;
262
+
263
+ _startPlaybackTimer ();
264
+ notifyListeners ();
265
+ }
266
+
267
+ void _startPlaybackTimer () {
268
+ if (_playbackIndex >= _playbackData! .length) {
269
+ stopPlayback ();
270
+ return ;
271
+ }
272
+
273
+ final currentRow = _playbackData! [_playbackIndex];
274
+ if (currentRow.length > 2 ) {
275
+ _currentPressure = double .tryParse (currentRow[2 ].toString ()) ?? 0.0 ;
276
+ if (currentRow.length > 3 ) {
277
+ _currentAltitude = double .tryParse (currentRow[3 ].toString ());
278
+ }
279
+ _currentTime = (_playbackIndex - 1 ).toDouble ();
280
+ _updateData ();
281
+ _playbackIndex++ ;
282
+ notifyListeners ();
283
+ } else {
284
+ logger.e (
285
+ 'Skipping playback row at index $_playbackIndex due to insufficient columns (found ${currentRow .length }, expected at least 3' );
286
+ _playbackIndex++ ;
287
+ notifyListeners ();
288
+ }
289
+
290
+ Duration interval = const Duration (seconds: 1 );
291
+
292
+ if (_playbackIndex < _playbackData! .length && _playbackIndex > 1 ) {
293
+ try {
294
+ final currentTimestamp =
295
+ int .tryParse (_playbackData! [_playbackIndex - 1 ][0 ].toString ());
296
+ final nextTimestamp =
297
+ int .tryParse (_playbackData! [_playbackIndex][0 ].toString ());
298
+
299
+ if (currentTimestamp != null && nextTimestamp != null ) {
300
+ final timeDiff = nextTimestamp - currentTimestamp;
301
+ interval = Duration (milliseconds: timeDiff);
302
+ if (interval.inMilliseconds < 100 ) {
303
+ interval = const Duration (milliseconds: 100 );
304
+ } else if (interval.inMilliseconds > 10000 ) {
305
+ interval = const Duration (seconds: 10 );
306
+ }
307
+ }
308
+ } catch (e) {
309
+ interval = const Duration (seconds: 1 );
310
+ }
311
+ }
312
+
313
+ _playbackTimer = Timer (interval, () {
314
+ if (_isPlayingBack && ! _isPlaybackPaused) {
315
+ _startPlaybackTimer ();
316
+ }
317
+ });
318
+ }
319
+
320
+ Future <void > stopPlayback () async {
321
+ _isPlayingBack = false ;
322
+ _isPlaybackPaused = false ;
323
+ _playbackTimer? .cancel ();
324
+ _playbackData = null ;
325
+ _playbackIndex = 0 ;
326
+
327
+ _pressureData.clear ();
328
+ pressureChartData.clear ();
329
+ _timeData.clear ();
330
+ _pressureSum = 0 ;
331
+ _dataCount = 0 ;
332
+ _currentPressure = 0.0 ;
333
+ _currentTemperature = 0.0 ;
334
+ _currentAltitude = null ;
335
+ _currentTime = 0 ;
336
+ notifyListeners ();
337
+ onPlaybackEnd? .call ();
338
+ }
339
+
340
+ void pausePlayback () {
341
+ if (_isPlayingBack) {
342
+ _isPlaybackPaused = true ;
343
+ _playbackTimer? .cancel ();
344
+ notifyListeners ();
345
+ }
346
+ }
347
+
348
+ void resumePlayback () {
349
+ if (_isPlayingBack && _isPlaybackPaused) {
350
+ _isPlaybackPaused = false ;
351
+ _startPlaybackTimer ();
352
+ notifyListeners ();
353
+ }
354
+ }
355
+
235
356
void disposeSensors () {
236
357
logger.d ("Disposing sensors..." );
237
358
_barometerSubscription? .cancel ();
@@ -240,19 +361,21 @@ class BarometerStateProvider extends ChangeNotifier {
240
361
_timeTimer = null ;
241
362
_dataTimer? .cancel ();
242
363
_dataTimer = null ;
364
+ _playbackTimer? .cancel ();
243
365
_bmp180Sensor = null ;
244
366
_sensorAvailable = false ;
245
367
}
246
368
247
369
@override
248
370
void dispose () {
249
371
_configProvider.removeListener (_onConfigChanged);
372
+ _playbackTimer? .cancel ();
250
373
disposeSensors ();
251
374
super .dispose ();
252
375
}
253
376
254
377
void _updateData () {
255
- if (! _sensorAvailable) return ;
378
+ if (! _sensorAvailable && ! _isPlayingBack ) return ;
256
379
257
380
final pressure = _currentPressure;
258
381
final time = _currentTime;
0 commit comments