feat: offer to calibrate sensor after provisioning
This commit is contained in:
@@ -4,7 +4,9 @@ import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../../data/sources/ble/ble_provisioner.dart';
|
||||
import '../../data/sources/local/credential_store.dart';
|
||||
import '../../domain/models/sensor.dart';
|
||||
import '../../providers.dart';
|
||||
import '../sensors/calibration_sheet.dart';
|
||||
|
||||
enum _Step { scan, configure, done }
|
||||
|
||||
@@ -30,6 +32,7 @@ class _BleProvisionSheetState extends ConsumerState<BleProvisionSheet> {
|
||||
|
||||
_Step _step = _Step.scan;
|
||||
BleScanResult? _selected;
|
||||
Sensor? _provisionedSensor;
|
||||
bool _provisioning = false;
|
||||
bool _mqttOverrideEnabled = false;
|
||||
bool _usingNewWifiConnection = true;
|
||||
@@ -102,7 +105,7 @@ class _BleProvisionSheetState extends ConsumerState<BleProvisionSheet> {
|
||||
mqttHost: mqttHost,
|
||||
mqttPort: mqttPort,
|
||||
);
|
||||
await ref
|
||||
_provisionedSensor = await ref
|
||||
.read(sensorRepositoryProvider)
|
||||
.createSensor(_selected!.name, name: _selected!.name);
|
||||
|
||||
@@ -254,12 +257,26 @@ class _BleProvisionSheetState extends ConsumerState<BleProvisionSheet> {
|
||||
),
|
||||
_DoneStep(
|
||||
onGoToFloorPlan: () {
|
||||
final router = GoRouter.of(context);
|
||||
Navigator.of(context).pop();
|
||||
router.go('/floorplan');
|
||||
if (_provisionedSensor != null) {
|
||||
_placeOnFloorPlan(context, _provisionedSensor!);
|
||||
}
|
||||
},
|
||||
onAddAnother: _reset,
|
||||
onDone: () => Navigator.of(context).pop(),
|
||||
onCalibrate: _provisionedSensor == null
|
||||
? null
|
||||
: () {
|
||||
final sensor = _provisionedSensor!;
|
||||
Navigator.of(
|
||||
context,
|
||||
rootNavigator: true,
|
||||
).pop();
|
||||
showCalibrationSheet(
|
||||
context,
|
||||
sensor.id,
|
||||
sensor.sensorId,
|
||||
);
|
||||
},
|
||||
),
|
||||
]
|
||||
.map(
|
||||
@@ -276,6 +293,16 @@ class _BleProvisionSheetState extends ConsumerState<BleProvisionSheet> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _placeOnFloorPlan(BuildContext context, Sensor sensor) {
|
||||
final router = GoRouter.of(context);
|
||||
final fromSensors =
|
||||
router.routeInformationProvider.value.uri.path == '/sensors';
|
||||
ref.read(sensorPlacementProvider.notifier).state = sensor;
|
||||
ref.read(sensorPlacementOriginSensorsProvider.notifier).state = fromSensors;
|
||||
Navigator.of(context, rootNavigator: true).pop();
|
||||
router.go('/floorplan');
|
||||
}
|
||||
}
|
||||
|
||||
class _ScanPage extends StatefulWidget {
|
||||
@@ -491,9 +518,7 @@ class _ConfigurePageState extends State<_ConfigurePage> {
|
||||
border: const OutlineInputBorder(),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
_obscurePassword
|
||||
? Icons.visibility_off
|
||||
: Icons.visibility,
|
||||
_obscurePassword ? Icons.visibility_off : Icons.visibility,
|
||||
),
|
||||
onPressed: () =>
|
||||
setState(() => _obscurePassword = !_obscurePassword),
|
||||
@@ -595,14 +620,17 @@ class _DoneStep extends StatelessWidget {
|
||||
required this.onGoToFloorPlan,
|
||||
required this.onAddAnother,
|
||||
required this.onDone,
|
||||
this.onCalibrate,
|
||||
});
|
||||
|
||||
final VoidCallback onGoToFloorPlan;
|
||||
final VoidCallback onAddAnother;
|
||||
final VoidCallback onDone;
|
||||
final VoidCallback? onCalibrate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
child: Column(
|
||||
@@ -613,22 +641,36 @@ class _DoneStep extends StatelessWidget {
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
'Sensor provisioned!',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
style: theme.textTheme.titleLarge,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'The sensor will appear in the list once it connects to the network. '
|
||||
'Open the floor plan to place it.',
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
style: theme.textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
FilledButton.icon(
|
||||
icon: const Icon(Icons.map_outlined),
|
||||
icon: const Icon(Icons.gps_fixed),
|
||||
label: const Text('Place on floor plan'),
|
||||
onPressed: onGoToFloorPlan,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
OutlinedButton.icon(
|
||||
icon: const Icon(Icons.tune),
|
||||
label: const Text('Calibrate sensor'),
|
||||
onPressed: onCalibrate,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'For best accuracy, calibrate after mounting the sensor in its intended position.',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
OutlinedButton.icon(
|
||||
icon: const Icon(Icons.add),
|
||||
|
||||
Reference in New Issue
Block a user