Skip to content

Commit f0c2494

Browse files
committed
Dust implementation without logic
1 parent 0aa77ec commit f0c2494

6 files changed

Lines changed: 303 additions & 10 deletions

File tree

lib/l10n/app_en.arb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@
334334
"manualMode": "Manual Mode",
335335
"frequencyChange": "Stop playback to change frequency.",
336336
"playBackStop": "Playback stopped",
337+
"dustSensorIntro": "Connect pins according to pin diagram and start measuring. Power up the sensor using VCC pin in PSLab and connect data pin to CH1. Make sure the ground wire is connected to one of the GND pins in PSLab.",
337338
"soundMeterIntro": "Sound meter Introduction",
338339
"soundMeterDescFull": "To measure the loudness in the environment in decibel(dB)",
339340
"luxMeterDescFull": "The Lux meter can be used to measure the ambient light intensity. This instruments is compatible with either the built-in light sensor on any Android device or the BH-1750 light sensor.",
@@ -674,5 +675,8 @@
674675
"good": "Good",
675676
"moderate": "Moderate",
676677
"unhealthy": "Unhealthy",
677-
"hazardous": "Hazardous"
678+
"hazardous": "Hazardous",
679+
"dustSensorConfig": "Dust Sensor Configurations",
680+
"dustUpdatePeriodHint": "Please provide time interval at which data will be updated (100 ms to 1000 ms)",
681+
"dustHighLimitHint": "Please provide the maximum limit of PPM value to be recorded (0.0 PPM to 5.0 PPM)"
678682
}

lib/models/dust_sensor_config.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
class DustSensorConfig {
2+
final int updatePeriod;
3+
final double highLimit;
4+
final String activeSensor;
5+
final bool includeLocationData;
6+
7+
const DustSensorConfig({
8+
this.updatePeriod = 1000,
9+
this.highLimit = 4.0,
10+
this.activeSensor = 'In-built Sensor',
11+
this.includeLocationData = true,
12+
});
13+
14+
DustSensorConfig copyWith({
15+
int? updatePeriod,
16+
double? highLimit,
17+
String? activeSensor,
18+
bool? includeLocationData,
19+
}) {
20+
return DustSensorConfig(
21+
updatePeriod: updatePeriod ?? this.updatePeriod,
22+
highLimit: highLimit ?? this.highLimit,
23+
activeSensor: activeSensor ?? this.activeSensor,
24+
includeLocationData: includeLocationData ?? this.includeLocationData,
25+
);
26+
}
27+
28+
Map<String, dynamic> toJson() {
29+
return {
30+
'updatePeriod': updatePeriod,
31+
'highLimit': highLimit,
32+
'activeSensor': activeSensor,
33+
'includeLocationData': includeLocationData,
34+
};
35+
}
36+
37+
factory DustSensorConfig.fromJson(Map<String, dynamic> json) {
38+
return DustSensorConfig(
39+
updatePeriod: json['updatePeriod'] ?? 1000,
40+
highLimit: (json['highLimit'] ?? 4.0).toDouble(),
41+
activeSensor: json['activeSensor'] ?? 'In-built Sensor',
42+
includeLocationData: json['includeLocationData'] ?? true,
43+
);
44+
}
45+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import 'package:flutter/foundation.dart';
2+
import 'dart:convert';
3+
import 'package:shared_preferences/shared_preferences.dart';
4+
import 'package:pslab/models/dust_sensor_config.dart';
5+
6+
class DustSensorConfigProvider extends ChangeNotifier {
7+
DustSensorConfig _config = const DustSensorConfig();
8+
DustSensorConfig get config => _config;
9+
10+
DustSensorConfigProvider() {
11+
_loadConfigFromPrefs();
12+
}
13+
14+
Future<void> _loadConfigFromPrefs() async {
15+
final prefs = await SharedPreferences.getInstance();
16+
final jsonString = prefs.getString('dust_config');
17+
if (jsonString != null) {
18+
final Map<String, dynamic> jsonMap = json.decode(jsonString);
19+
_config = DustSensorConfig.fromJson(jsonMap);
20+
notifyListeners();
21+
}
22+
}
23+
24+
Future<void> _saveConfigToPrefs() async {
25+
final prefs = await SharedPreferences.getInstance();
26+
await prefs.setString('dust_config', json.encode(_config.toJson()));
27+
}
28+
29+
void updateConfig(DustSensorConfig newConfig) {
30+
_config = newConfig;
31+
notifyListeners();
32+
_saveConfigToPrefs();
33+
}
34+
35+
void updateUpdatePeriod(int updatePeriod) {
36+
_config = _config.copyWith(updatePeriod: updatePeriod);
37+
notifyListeners();
38+
_saveConfigToPrefs();
39+
}
40+
41+
void updateHighLimit(double highLimit) {
42+
_config = _config.copyWith(highLimit: highLimit);
43+
notifyListeners();
44+
_saveConfigToPrefs();
45+
}
46+
47+
void updateActiveSensor(String activeSensor) {
48+
_config = _config.copyWith(activeSensor: activeSensor);
49+
notifyListeners();
50+
_saveConfigToPrefs();
51+
}
52+
53+
void updateIncludeLocationData(bool includeLocationData) {
54+
_config = _config.copyWith(includeLocationData: includeLocationData);
55+
notifyListeners();
56+
_saveConfigToPrefs();
57+
}
58+
59+
void resetToDefaults() {
60+
_config = const DustSensorConfig();
61+
notifyListeners();
62+
_saveConfigToPrefs();
63+
}
64+
}

lib/providers/dust_sensor_state_provider.dart

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:intl/intl.dart';
88

99
import '../l10n/app_localizations.dart';
1010
import '../others/logger_service.dart';
11+
import 'dust_sensor_config_provider.dart';
1112
import 'locator.dart';
1213

1314
class DustSensorStateProvider extends ChangeNotifier {
@@ -37,12 +38,20 @@ class DustSensorStateProvider extends ChangeNotifier {
3738
bool get isPlayingBack => _isPlayingBack;
3839
bool get isPlaybackPaused => _isPlaybackPaused;
3940

41+
DustSensorConfigProvider? _configProvider;
42+
4043
Function(String)? onSensorError;
4144
Function? onPlaybackEnd;
4245

4346
Position? currentPosition;
4447
StreamSubscription? _locationStream;
4548

49+
void setConfigProvider(DustSensorConfigProvider configProvider) {
50+
_configProvider = configProvider;
51+
}
52+
53+
DustSensorConfigProvider? get configProvider => _configProvider;
54+
4655
Future<void> _startGeoLocationUpdates() async {
4756
bool serviceEnabled;
4857
LocationPermission permission;
@@ -90,8 +99,11 @@ class DustSensorStateProvider extends ChangeNotifier {
9099
notifyListeners();
91100
});
92101

93-
_dustTimer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
94-
// Placeholder for dust sensor reading logic
102+
int interval = _configProvider?.config.updatePeriod ?? 1000;
103+
_dustTimer = Timer.periodic(Duration(milliseconds: interval), (timer) {
104+
105+
/// TO DO
106+
95107
notifyListeners();
96108
});
97109
} catch (e) {
@@ -123,6 +135,7 @@ class DustSensorStateProvider extends ChangeNotifier {
123135

124136
_dustData.clear();
125137
dustChartData.clear();
138+
ppmChartData.clear();
126139
_timeData.clear();
127140
_startTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
128141
_currentTime = 0;
@@ -192,6 +205,7 @@ class DustSensorStateProvider extends ChangeNotifier {
192205

193206
_dustData.clear();
194207
dustChartData.clear();
208+
ppmChartData.clear();
195209
_timeData.clear();
196210
_dustSum = 0;
197211
_dataCount = 0;
@@ -237,8 +251,12 @@ class DustSensorStateProvider extends ChangeNotifier {
237251
now.millisecondsSinceEpoch.toString(),
238252
dateFormat.format(now),
239253
dust.toStringAsFixed(2),
240-
currentPosition?.latitude.toString() ?? 0,
241-
currentPosition?.longitude.toString() ?? 0
254+
_configProvider!.config.includeLocationData
255+
? currentPosition?.latitude.toString() ?? 0
256+
: 0,
257+
_configProvider!.config.includeLocationData
258+
? currentPosition?.longitude.toString() ?? 0
259+
: 0
242260
]);
243261
}
244262
_dustData.add(dust);
@@ -256,6 +274,7 @@ class DustSensorStateProvider extends ChangeNotifier {
256274
_dustMax = _dustData.reduce(max);
257275
}
258276
dustChartData.clear();
277+
ppmChartData.clear();
259278
for (int i = 0; i < _dustData.length; i++) {
260279
dustChartData.add(FlSpot(_timeData[i], _dustData[i]));
261280
ppmChartData.add(FlSpot(_timeData[i], _dustData[i] * 0.1));
@@ -264,7 +283,9 @@ class DustSensorStateProvider extends ChangeNotifier {
264283
}
265284

266285
Future<void> startRecording() async {
267-
await _startGeoLocationUpdates();
286+
if (_configProvider!.config.includeLocationData) {
287+
await _startGeoLocationUpdates();
288+
}
268289
_isRecording = true;
269290
_recordedData = [
270291
['Timestamp', 'DateTime', 'Readings', 'Latitude', 'Longitude']
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter/services.dart';
3+
import 'package:provider/provider.dart';
4+
import 'package:pslab/providers/dust_sensor_config_provider.dart';
5+
import 'package:pslab/view/widgets/config_widgets.dart';
6+
import '../l10n/app_localizations.dart';
7+
import '../providers/locator.dart';
8+
import '../theme/colors.dart';
9+
10+
class DustSensorConfigScreen extends StatefulWidget {
11+
const DustSensorConfigScreen({super.key});
12+
@override
13+
State<DustSensorConfigScreen> createState() => _DustSensorConfigScreenState();
14+
}
15+
16+
class _DustSensorConfigScreenState extends State<DustSensorConfigScreen> {
17+
AppLocalizations appLocalizations = getIt.get<AppLocalizations>();
18+
final TextEditingController _updatePeriodController = TextEditingController();
19+
final TextEditingController _highLimitController = TextEditingController();
20+
21+
@override
22+
void dispose() {
23+
_updatePeriodController.dispose();
24+
_highLimitController.dispose();
25+
super.dispose();
26+
}
27+
28+
@override
29+
Widget build(BuildContext context) {
30+
return Scaffold(
31+
backgroundColor: Theme.of(context).colorScheme.surface,
32+
resizeToAvoidBottomInset: true,
33+
appBar: AppBar(
34+
systemOverlayStyle: SystemUiOverlayStyle(
35+
statusBarColor: appBarColor,
36+
statusBarIconBrightness: Brightness.light,
37+
statusBarBrightness: Brightness.dark,
38+
),
39+
leading: Builder(builder: (context) {
40+
return IconButton(
41+
onPressed: () {
42+
Navigator.maybePop(context);
43+
},
44+
icon: Icon(
45+
Icons.arrow_back,
46+
color: appBarContentColor,
47+
),
48+
);
49+
}),
50+
backgroundColor: primaryRed,
51+
title: Text(
52+
appLocalizations.dustSensorConfig,
53+
style: TextStyle(
54+
color: appBarContentColor,
55+
fontSize: 15,
56+
),
57+
),
58+
),
59+
body: SafeArea(
60+
child: Padding(
61+
padding: const EdgeInsets.symmetric(horizontal: 16.0),
62+
child: Consumer<DustSensorConfigProvider>(
63+
builder: (context, provider, child) {
64+
_updatePeriodController.text =
65+
provider.config.updatePeriod.toString();
66+
_highLimitController.text = provider.config.highLimit.toString();
67+
68+
return SingleChildScrollView(
69+
child: Column(
70+
children: [
71+
ConfigInputItem(
72+
title: appLocalizations.updatePeriod,
73+
value:
74+
"${provider.config.updatePeriod} ${appLocalizations.ms}",
75+
controller: _updatePeriodController,
76+
hint: appLocalizations.dustUpdatePeriodHint,
77+
onChanged: (value) {
78+
try {
79+
int updatePeriod = int.parse(value);
80+
if (updatePeriod > 1000 || updatePeriod < 100) {
81+
throw const FormatException();
82+
}
83+
provider.updateUpdatePeriod(updatePeriod);
84+
} catch (e) {
85+
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
86+
content: Text(
87+
appLocalizations.updatePeriodErrorMessage)));
88+
}
89+
},
90+
),
91+
ConfigInputItem(
92+
title: appLocalizations.highLimit,
93+
value:
94+
"${provider.config.highLimit} ${appLocalizations.ppm}",
95+
controller: _highLimitController,
96+
hint: appLocalizations.dustHighLimitHint,
97+
onChanged: (value) {
98+
try {
99+
double highLimit = double.parse(value);
100+
if (highLimit > 5.0 || highLimit < 0.0) {
101+
throw const FormatException();
102+
}
103+
provider.updateHighLimit(highLimit);
104+
} catch (e) {
105+
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
106+
content: Text(
107+
appLocalizations.highLimitErrorMessage)));
108+
}
109+
},
110+
),
111+
ConfigDropdownItem(
112+
title: appLocalizations.activeSensor,
113+
selectedValue: provider.config.activeSensor,
114+
options: [
115+
ConfigOption(
116+
value: 'In-built Sensor',
117+
displayName: appLocalizations.inBuiltSensor),
118+
const ConfigOption(
119+
value: 'SDS011', displayName: 'SDS011'),
120+
],
121+
onChanged: (value) {
122+
provider.updateActiveSensor(value);
123+
},
124+
),
125+
ConfigCheckboxItem(
126+
title: appLocalizations.locationData,
127+
subtitle: appLocalizations.locationDataHint,
128+
value: provider.config.includeLocationData,
129+
onChanged: (value) {
130+
provider.updateIncludeLocationData(value);
131+
},
132+
),
133+
],
134+
),
135+
);
136+
},
137+
),
138+
),
139+
),
140+
);
141+
}
142+
}

0 commit comments

Comments
 (0)