feat: harden geofence and distance diagnostics

This commit is contained in:
Artem Kokos
2026-05-01 09:13:23 +07:00
parent 872ddf9513
commit 91a494adf5
20 changed files with 1639 additions and 260 deletions

View File

@@ -2,28 +2,48 @@ import 'package:workmanager/workmanager.dart';
import '../../models/home_config.dart';
import '../../services/geofence_worker.dart';
import 'services/geofence_runtime_store.dart';
/// Синхронизировать состояние фонового таска с настройками домов.
/// Вызывать при старте приложения и при изменении настроек.
///
/// Если хотя бы один дом имеет geofenceReady -- регистрируем
/// периодический таск. Иначе -- отменяем.
Future<void> syncGeofenceTask(List<HomeConfig> homes) async {
final needGeofence = homes.any((h) => h.geofenceReady);
/// Геофенс работает только для текущего активного дома.
/// Если активный дом не готов -- таск снимается и runtime разоружается.
Future<void> syncGeofenceTask(
List<HomeConfig> homes, {
required HomeConfig? currentHome,
}) async {
final runtimeStore = GeofenceRuntimeStore();
final activeHome = currentHome;
final needGeofence =
activeHome != null &&
homes.any((home) => home.id == activeHome.id) &&
activeHome.geofenceReady;
if (needGeofence) {
await resetGeofenceFired();
await runtimeStore.armForHome(activeHome.id);
await Workmanager().registerPeriodicTask(
geofenceTaskUniqueName,
geofenceTaskName,
frequency: const Duration(minutes: 15),
constraints: Constraints(networkType: NetworkType.connected),
existingWorkPolicy: ExistingPeriodicWorkPolicy.replace,
backoffPolicy: BackoffPolicy.linear,
backoffPolicyDelay: const Duration(minutes: 1),
);
try {
await Workmanager().registerPeriodicTask(
geofenceTaskUniqueName,
geofenceTaskName,
frequency: const Duration(minutes: 15),
constraints: Constraints(networkType: NetworkType.connected),
existingWorkPolicy: ExistingPeriodicWorkPolicy.replace,
backoffPolicy: BackoffPolicy.linear,
backoffPolicyDelay: const Duration(minutes: 1),
);
} catch (_) {
// В тестах и на неполной платформенной инициализации
// не даём workmanager уронить остальное приложение.
}
} else {
await Workmanager().cancelByUniqueName(geofenceTaskUniqueName);
await runtimeStore.disarm();
try {
await Workmanager().cancelByUniqueName(geofenceTaskUniqueName);
} catch (_) {
// См. комментарий выше: runtime должен синхронизироваться
// даже если platform plugin недоступен.
}
}
}