Skip to content

Commit

Permalink
smoothed the time slider
Browse files Browse the repository at this point in the history
  • Loading branch information
pseudoincorrect committed Apr 1, 2021
1 parent 21d0076 commit d221dde
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 142 deletions.
2 changes: 1 addition & 1 deletion Mobile_app/smart_mask/.flutter-plugins-dependencies
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.0\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.0.0\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.0\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2021-04-01 14:36:27.567617","version":"2.0.3"}
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"android":[{"name":"flutter_blue","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\flutter_blue-0.7.2\\\\","dependencies":[]},{"name":"path_provider","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider-2.0.1\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_macos-2.0.0\\\\","dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.0+3\\\\","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_linux-2.0.0\\\\","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\maxim\\\\Programming\\\\SDKs\\\\Flutter\\\\flutter\\\\.pub-cache\\\\hosted\\\\pub.dartlang.org\\\\path_provider_windows-2.0.0\\\\","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_blue","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2021-04-01 16:39:01.550354","version":"2.0.3"}
2 changes: 1 addition & 1 deletion Mobile_app/smart_mask/lib/TODO
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Add low pass filter to data
Add High pass filter to data
Download data to file system
Add a home page with quick view of the sensor
handle sensor change in Analytics bloc
change time slider value to stream


-------------------------------------------------------------
IN PROCESS
-------------------------------------------------------------
change to millisec instead of DateTime in analyticsBloc


-------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:rxdart/rxdart.dart';
Expand All @@ -20,15 +19,11 @@ class AnalyticsBloc {
Sensor _selectedSensor = Sensor.sensor_1;
late AnalyticsState _analyticsState;

late BehaviorSubject<Sensor> _selectedSensorSubject;
late BehaviorSubject<TimeInterval> _timeRangeSubject;
late BehaviorSubject<List<SensorData>> _sensorDataProcessedSubject;
late BehaviorSubject<bool> _analyticsRefresh;
late BehaviorSubject<List<SensorData>> _sensorDataSubject;

AnalyticsBloc() {
_selectedSensorSubject = BehaviorSubject<Sensor>();
_timeRangeSubject = BehaviorSubject<TimeInterval>();
_sensorDataProcessedSubject = BehaviorSubject<List<SensorData>>();
_sensorDataSubject = BehaviorSubject<List<SensorData>>();
_analyticsRefresh = BehaviorSubject<bool>();
_analyticsRefresh.stream.listen((event) => processAnalytics());
setSelectedSensor(_selectedSensor);
Expand All @@ -38,17 +33,16 @@ class AnalyticsBloc {
Future<TimeInterval> getAvailableInterval() async {
final start = await _sensorDataRepo.getOldestSensorData(_selectedSensor);
final end = await _sensorDataRepo.getNewestSensorData(_selectedSensor);
if (start == null || end == null)
return TimeInterval(DateTime.now(), DateTime.now());

final startDate = DateTime.fromMillisecondsSinceEpoch(start.timeStamp);
final endDate = DateTime.fromMillisecondsSinceEpoch(end.timeStamp);
return TimeInterval(startDate, endDate);
if (start == null || end == null) {
var now = DateTime.now().millisecondsSinceEpoch;
return TimeInterval(now, now);
}
return TimeInterval(start.timeStamp, end.timeStamp);
}

List<SensorData> getDataWindow() {
final leftMs = _analyticsState._timeWindow.start.millisecondsSinceEpoch;
final rightMs = _analyticsState._timeWindow.end.millisecondsSinceEpoch;
final leftMs = _analyticsState._timeWindow.start;
final rightMs = _analyticsState._timeWindow.end;
final winList = _analyticsState.dataRaw
.where((d) => d.timeStamp >= leftMs && d.timeStamp <= rightMs)
.toList();
Expand All @@ -57,26 +51,26 @@ class AnalyticsBloc {

processAnalytics() async {
calculateTimeWindow();
_sensorDataProcessedSubject.sink.add(getDataWindow());
// _sensorDataProcessedSubject.sink.add(_analyticsState.dataRaw);
_sensorDataSubject.sink.add(getDataWindow());
}

Future<List<SensorData>> getSensorData(TimeInterval interval) async {
final start = DateTime.fromMillisecondsSinceEpoch(interval.start);
final end = DateTime.fromMillisecondsSinceEpoch(interval.end);
List<SensorData> sensorData = await _sensorDataRepo.getSensorData(
_selectedSensor,
interval: [interval.start, interval.end],
interval: [start, end],
);
return sensorData;
}

Stream<List<SensorData>> getSensorDataStream() {
return _sensorDataProcessedSubject.stream;
return _sensorDataSubject.stream;
}

void calculateTimeWindow() {
final startMs =
_analyticsState.workTimeInterval.start.millisecondsSinceEpoch;
final endMs = _analyticsState.workTimeInterval.end.millisecondsSinceEpoch;
final startMs = _analyticsState.workTimeInterval.start;
final endMs = _analyticsState.workTimeInterval.end;
final posInTicks = _analyticsState.timePosInTicks;

final centerMs =
Expand All @@ -88,18 +82,13 @@ class AnalyticsBloc {
var windowRightMs = centerMs + zoomDelta;
windowRightMs = windowRightMs < endMs ? windowRightMs : endMs;

_analyticsState._timeWindow.start =
DateTime.fromMillisecondsSinceEpoch(windowLeftMs);
_analyticsState._timeWindow.end =
DateTime.fromMillisecondsSinceEpoch(windowRightMs);

_analyticsState.timeWindow = TimeInterval(
DateTime.fromMillisecondsSinceEpoch(windowLeftMs),
DateTime.fromMillisecondsSinceEpoch(windowRightMs));
_analyticsState.timeWindow = TimeInterval(windowLeftMs, windowRightMs);
}

print(
"time windows : ${_analyticsState._timeWindow.start.minute}:${_analyticsState._timeWindow.start.second}"
" to ${_analyticsState._timeWindow.end.minute}:${_analyticsState._timeWindow.end.second}");
void changeSensor() async {
final ti = await getAvailableInterval();
_analyticsState.dataRaw = await getSensorData(ti);
triggerAnalyticsRefresh();
}

void refreshSensorData() async {
Expand All @@ -110,19 +99,11 @@ class AnalyticsBloc {
triggerAnalyticsRefresh();
}

Stream<TimeInterval> get timeRangeStream => _timeRangeSubject.stream;

set timeRange(TimeInterval interval) {
_timeRangeSubject.add(interval);
getSensorData(interval);
}
get selectedSensor => _selectedSensor;

void setSelectedSensor(Sensor sensor) {
_selectedSensorSubject.add(sensor);
}

Stream<Sensor> getSelectedSensorStream() {
return _selectedSensorSubject.stream;
_selectedSensor = sensor;
changeSensor();
}

Stream<bool> getAnalyticsRefreshStream() {
Expand Down Expand Up @@ -167,24 +148,23 @@ class AnalyticsBloc {
}

dispose() {
_sensorDataProcessedSubject.close();
_selectedSensorSubject.close();
_timeRangeSubject.close();
_sensorDataSubject.close();
_analyticsRefresh.close();
}
}

class TimeInterval {
late DateTime start;
late DateTime end;
late int start;
late int end;

TimeInterval(this.start, this.end);

factory TimeInterval.fromMsSinceEpoch(RangeValues range) {
DateTime dateStart =
DateTime.fromMillisecondsSinceEpoch(range.start.toInt());
DateTime dateEnd = DateTime.fromMillisecondsSinceEpoch(range.end.toInt());
return TimeInterval(dateStart, dateEnd);
}
// factory TimeInterval.fromMsSinceEpoch(RangeValues range) {
// DateTime dateStart =
// DateTime.fromMillisecondsSinceEpoch(range.start.toInt());
// DateTime dateEnd = DateTime.fromMillisecondsSinceEpoch(range.end.toInt());
// return TimeInterval(dateStart, dateEnd);
// }
}

class AnalyticsState {
Expand All @@ -202,7 +182,10 @@ class AnalyticsState {
dataProcessed = [];
_lowPassFilter = 100.0;
_highPassFilter = 0.2;
_workTimeInterval = TimeInterval(DateTime.now(), DateTime.now());
_workTimeInterval = TimeInterval(
DateTime.now().millisecondsSinceEpoch,
DateTime.now().millisecondsSinceEpoch,
);
resetWorkInterval();
}

Expand Down Expand Up @@ -238,19 +221,20 @@ class AnalyticsState {
var start = ti.start;
var end = ti.end;
// start is max one hour before end
if (ti.start.isBefore(ti.end.subtract(Duration(hours: 1))))
start = ti.end.subtract(Duration(hours: 1));

if (ti.start < (ti.end - Duration(hours: 1).inMilliseconds))
start = ti.end - Duration(hours: 1).inMilliseconds;

_workTimeInterval = TimeInterval(start, end);
}

TimeInterval get timeWindow => _timeWindow;

set timeWindow(TimeInterval interval) {
final startMs = interval.start.millisecondsSinceEpoch;
final endMs = interval.end.millisecondsSinceEpoch;
final wStartMs = _workTimeInterval.start.millisecondsSinceEpoch;
final wEndMs = _workTimeInterval.end.millisecondsSinceEpoch;
final startMs = interval.start;
final endMs = interval.end;
final wStartMs = _workTimeInterval.start;
final wEndMs = _workTimeInterval.end;

if (startMs >= wStartMs && endMs <= wEndMs) _timeWindow = interval;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class GraphsScreen extends StatelessWidget {
]),
subtitle: SensorGraph(
sensorDataStream: sensorDataBloc.getStream(sensor),
sensor: sensor,
height: graphsHeight / (Sensor.values.length * 2),
),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ class GraphDetailsScreen extends StatelessWidget {
height: graphsHeight,
child: SensorGraph(
sensorDataStream: sensorDataBloc.getStream(sensor),
sensor: sensor,
height: graphsHeight / (Sensor.values.length * 2),
),
),
Expand Down
82 changes: 21 additions & 61 deletions Mobile_app/smart_mask/lib/src/ui/widgets/analytics_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,9 @@ class AnalyticsSensorGraph extends StatelessWidget {
@override
Widget build(BuildContext context) {
AnalyticsBloc bloc = AnalyticsProvider.of(context);

return StreamBuilder(
stream: bloc.getSelectedSensorStream(),
builder: (BuildContext context, AsyncSnapshot<Sensor> snapshot) {
if (snapshot.hasError) Text("ConnectionError");
switch (snapshot.connectionState) {
case ConnectionState.none:
case ConnectionState.waiting:
case ConnectionState.done:
return Text("Sensor Selection not ready");
case ConnectionState.active:
return _buildAnalyticsSensorGraph(snapshot.data!, bloc);
// return Text("Soon, there will be a graph here"),
}
},
);
}

Widget _buildAnalyticsSensorGraph(Sensor sensor, AnalyticsBloc bloc) {
return Container(
child: SizedBox(
height: graphsHeight,
child: SensorGraph(
sensorDataStream: bloc.getSensorDataStream(),
sensor: sensor,
height: graphsHeight / (Sensor.values.length * 2),
),
),
return SensorGraph(
sensorDataStream: bloc.getSensorDataStream(),
height: graphsHeight,
);
}
}
Expand Down Expand Up @@ -92,27 +67,7 @@ class SensorSelectAnalyticsDropButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
AnalyticsBloc bloc = AnalyticsProvider.of(context);

return StreamBuilder(
stream: bloc.getSelectedSensorStream(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasError) return Text("error");
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text("Drop Button ConnectionNone");
case ConnectionState.waiting:
return Text("Drop Button ConnectionWaiting");
case ConnectionState.done:
return Text("Drop Button ConnectionDone");
case ConnectionState.active:
return _buildSensorSelectAnalyticsDropButton(snapshot.data, bloc);
}
},
);
}

Widget _buildSensorSelectAnalyticsDropButton(
Sensor sensor, AnalyticsBloc bloc) {
Sensor sensor = bloc.selectedSensor;
final List<String> sensors =
Sensor.values.map((Sensor s) => sensorEnumToString(s)).toList();

Expand Down Expand Up @@ -153,7 +108,7 @@ class _IntervalSliderState extends State<IntervalSlider> {
@override
void initState() {
super.initState();
_currentSliderValue = 0;
_currentSliderValue = 500;
}

@override
Expand Down Expand Up @@ -203,17 +158,22 @@ class _IntervalSliderState extends State<IntervalSlider> {
}

Widget timeSlider() {
return Slider(
value: _currentSliderValue,
min: 0,
max: 1000,
divisions: 99,
onChangeEnd: (double value) {
bloc.setTimefromInt(value.toInt());
},
onChanged: (double x) {
setState(() => _currentSliderValue = x);
},
return SliderTheme(
data: SliderTheme.of(context).copyWith(
inactiveTrackColor: Theme.of(context).accentColor,
activeTrackColor: Theme.of(context).accentColor,
trackShape: RectangularSliderTrackShape(),
),
child: Slider(
value: _currentSliderValue,
min: 0,
max: 1000,
divisions: 99,
onChanged: (double x) {
setState(() => _currentSliderValue = x);
bloc.setTimefromInt(x.toInt());
},
),
);
}

Expand Down
Loading

0 comments on commit d221dde

Please sign in to comment.