Skip to content
Merged
20 changes: 19 additions & 1 deletion lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ String degreeSymbol = '°';
String enterAngleRange = 'Enter angle (0 - 360)';
String errorCannotBeEmpty = 'Cannot be empty';
String servoValidNumberRange = 'Please enter a valid number between 0 and 360';
String ok = 'Ok';
String ok = 'OK';
String roboticArm = 'Robotic Arm';
String play = 'Play';
String pause = 'Pause';
Expand Down Expand Up @@ -368,3 +368,21 @@ String shareAppMenu = 'Share App';
String privacyPolicyMenu = 'Privacy Policy';
String shopLink = 'https://pslab.io/shop/';
String shopError = 'Could not open the shop link';
String showLuxmeterConfig = 'Lux Meter Configurations';
String luxmeterConfigurations = 'Lux Meter Configurations';
String updatePeriod = 'Update Period';
String updatePeriodHint =
'Please provide time interval at which data will be updated (100 ms to 1000 ms)';
String highLimit = 'High Limit';
String highLimitHint =
'Please provide the maximum limit of lux value to be recorded (10 Lx to 10000 Lx)';
String sensorGain = 'Sensor Gain';
String sensorGainHint = 'Please set gain of the sensor';
String locationData = 'Include Location Data';
String locationDataHint = 'Include the location data in the logged file';
String activeSensor = 'Active Sensor';
String ms = 'ms';
String inBuiltSensor = 'In-built Sensor';
String updatePeriodErrorMessage =
'Entered update period is not within the limits!';
String highLimitErrorMessage = 'Entered High limit is not within the limits!';
51 changes: 51 additions & 0 deletions lib/models/luxmeter_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
class LuxMeterConfig {
final int updatePeriod;
final int highLimit;
final String activeSensor;
final int sensorGain;
final bool includeLocationData;

const LuxMeterConfig({
this.updatePeriod = 1000,
this.highLimit = 2000,
this.activeSensor = 'In-built Sensor',
this.sensorGain = 1,
this.includeLocationData = true,
});

LuxMeterConfig copyWith({
int? updatePeriod,
int? highLimit,
String? activeSensor,
int? sensorGain,
bool? includeLocationData,
}) {
return LuxMeterConfig(
updatePeriod: updatePeriod ?? this.updatePeriod,
highLimit: highLimit ?? this.highLimit,
activeSensor: activeSensor ?? this.activeSensor,
sensorGain: sensorGain ?? this.sensorGain,
includeLocationData: includeLocationData ?? this.includeLocationData,
);
}

Map<String, dynamic> toJson() {
return {
'updatePeriod': updatePeriod,
'highLimit': highLimit,
'activeSensor': activeSensor,
'sensorGain': sensorGain,
'includeLocationData': includeLocationData,
};
}

factory LuxMeterConfig.fromJson(Map<String, dynamic> json) {
return LuxMeterConfig(
updatePeriod: json['updatePeriod'] ?? 1000,
highLimit: json['highLimit'] ?? 2000,
activeSensor: json['activeSensor'] ?? 'In-built Sensor',
sensorGain: json['sensorGain'] ?? 1,
includeLocationData: json['includeLocationData'] ?? true,
);
}
}
71 changes: 71 additions & 0 deletions lib/providers/luxmeter_config_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import 'package:flutter/foundation.dart';
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:pslab/models/luxmeter_config.dart';

class LuxMeterConfigProvider extends ChangeNotifier {
LuxMeterConfig _config = const LuxMeterConfig();

LuxMeterConfig get config => _config;

LuxMeterConfigProvider() {
_loadConfigFromPrefs();
}

Future<void> _loadConfigFromPrefs() async {
final prefs = await SharedPreferences.getInstance();
final jsonString = prefs.getString('lux_config');
if (jsonString != null) {
final Map<String, dynamic> jsonMap = json.decode(jsonString);
_config = LuxMeterConfig.fromJson(jsonMap);
notifyListeners();
}
}

Future<void> _saveConfigToPrefs() async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('lux_config', json.encode(_config.toJson()));
}

void updateConfig(LuxMeterConfig newConfig) {
_config = newConfig;
notifyListeners();
_saveConfigToPrefs();
}

void updateUpdatePeriod(int updatePeriod) {
_config = _config.copyWith(updatePeriod: updatePeriod);
notifyListeners();
_saveConfigToPrefs();
}

void updateHighLimit(int highLimit) {
_config = _config.copyWith(highLimit: highLimit);
notifyListeners();
_saveConfigToPrefs();
}

void updateActiveSensor(String activeSensor) {
_config = _config.copyWith(activeSensor: activeSensor);
notifyListeners();
_saveConfigToPrefs();
}

void updateSensorGain(int sensorGain) {
_config = _config.copyWith(sensorGain: sensorGain);
notifyListeners();
_saveConfigToPrefs();
}

void updateIncludeLocationData(bool includeLocationData) {
_config = _config.copyWith(includeLocationData: includeLocationData);
notifyListeners();
_saveConfigToPrefs();
}

void resetToDefaults() {
_config = const LuxMeterConfig();
notifyListeners();
_saveConfigToPrefs();
}
}
17 changes: 17 additions & 0 deletions lib/providers/luxmeter_state_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:pslab/others/logger_service.dart';
import 'package:light/light.dart';
import 'package:flutter/foundation.dart';
import 'package:pslab/constants.dart';
import 'package:pslab/providers/luxmeter_config_provider.dart';

class LuxMeterStateProvider extends ChangeNotifier {
double _currentLux = 0.0;
Expand All @@ -23,8 +24,23 @@ class LuxMeterStateProvider extends ChangeNotifier {
int _dataCount = 0;
bool _sensorAvailable = false;

LuxMeterConfigProvider? _configProvider;

Function(String)? onSensorError;

void setConfigProvider(LuxMeterConfigProvider configProvider) {
_configProvider = configProvider;
_configProvider?.addListener(_onConfigChanged);
}

void _onConfigChanged() {
if (_configProvider != null) {
// TODO
}
}

LuxMeterConfigProvider? get configProvider => _configProvider;

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

Expand Down Expand Up @@ -79,6 +95,7 @@ class LuxMeterStateProvider extends ChangeNotifier {

@override
void dispose() {
_configProvider?.removeListener(_onConfigChanged);
disposeSensors();
super.dispose();
}
Expand Down
1 change: 1 addition & 0 deletions lib/theme/colors.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Color snackBarContentColor = Colors.white;
Color guideDrawerBackgroundColor = Colors.white;
Color guideDrawerHeadingColor = Colors.black87;
Color guideDrawerHighlightColor = Colors.black54;
Color hintTextColor = Colors.grey;
List<Color> knobLabelColors = [
Color(0xFFD32F2F), // CH1
Color(0xFFD32F2F), // CAP
Expand Down
176 changes: 176 additions & 0 deletions lib/view/luxmeter_config_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:pslab/constants.dart';
import 'package:pslab/providers/luxmeter_config_provider.dart';
import 'package:pslab/view/widgets/config_widgets.dart';

import '../theme/colors.dart';

class LuxMeterConfigScreen extends StatefulWidget {
const LuxMeterConfigScreen({super.key});

@override
State<LuxMeterConfigScreen> createState() => _LuxMeterConfigScreenState();
}

class _LuxMeterConfigScreenState extends State<LuxMeterConfigScreen> {
final TextEditingController _updatePeriodController = TextEditingController();
final TextEditingController _highLimitController = TextEditingController();
final TextEditingController _sensorGainController = TextEditingController();

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
final provider =
Provider.of<LuxMeterConfigProvider>(context, listen: false);
_updatePeriodController.text = provider.config.updatePeriod.toString();
_highLimitController.text = provider.config.highLimit.toString();
_sensorGainController.text = provider.config.sensorGain.toString();
});
}

@override
void dispose() {
_updatePeriodController.dispose();
_highLimitController.dispose();
_sensorGainController.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).colorScheme.surface,
resizeToAvoidBottomInset: true,
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle(statusBarColor: appBarColor),
leading: Builder(builder: (context) {
return IconButton(
onPressed: () {
if (Navigator.canPop(context) &&
ModalRoute.of(context)?.settings.name == '/luxmeter') {
Navigator.popUntil(context, ModalRoute.withName('/luxmeter'));
} else {
Navigator.pushNamedAndRemoveUntil(
context,
'/luxmeter',
(route) => route.isFirst,
);
}
},
icon: Icon(
Icons.arrow_back,
color: appBarContentColor,
),
);
}),
backgroundColor: primaryRed,
title: Text(
luxmeterConfigurations,
style: TextStyle(
color: appBarContentColor,
fontSize: 15,
),
),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Consumer<LuxMeterConfigProvider>(
builder: (context, provider, child) {
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ConfigInputItem(
title: updatePeriod,
value: '${provider.config.updatePeriod} $ms',
controller: _updatePeriodController,
onChanged: (value) {
final intValue = int.tryParse(value);
if (intValue != null &&
intValue >= 100 &&
intValue <= 1000) {
provider.updateUpdatePeriod(intValue);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
updatePeriodErrorMessage,
style: TextStyle(color: snackBarContentColor),
),
backgroundColor: snackBarBackgroundColor),
);
}
},
hint: updatePeriodHint,
),
ConfigInputItem(
title: highLimit,
value: '${provider.config.highLimit} $lx',
controller: _highLimitController,
onChanged: (value) {
final intValue = int.tryParse(value);
if (intValue != null &&
intValue >= 10 &&
intValue <= 10000) {
provider.updateHighLimit(intValue);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
highLimitErrorMessage,
style: TextStyle(color: snackBarContentColor),
),
backgroundColor: snackBarBackgroundColor),
);
}
},
hint: highLimitHint,
),
ConfigDropdownItem(
title: activeSensor,
selectedValue: provider.config.activeSensor,
options: [
ConfigOption(
value: 'In-built Sensor',
displayName: inBuiltSensor),
ConfigOption(value: 'BH1750', displayName: 'BH1750'),
ConfigOption(value: 'TSL2561', displayName: 'TSL2561'),
],
onChanged: (value) {
provider.updateActiveSensor(value);
},
),
ConfigInputItem(
title: sensorGain,
value: provider.config.sensorGain.toString(),
controller: _sensorGainController,
onChanged: (value) {
final intValue = int.tryParse(value);
if (intValue != null) {
provider.updateSensorGain(intValue);
}
},
hint: sensorGainHint,
),
ConfigCheckboxItem(
title: locationData,
subtitle: locationDataHint,
value: provider.config.includeLocationData,
onChanged: (value) {
provider.updateIncludeLocationData(value);
},
),
],
),
);
},
),
),
),
);
}
}
Loading