mirror of
https://github.com/zjs81/meshcore-open.git
synced 2026-06-14 22:55:12 +10:00
Merge branch 'dev' of https://github.com/zjs81/meshcore-open into dev
This commit is contained in:
@@ -1,8 +1,19 @@
|
||||
import '../utils/platform_info.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
|
||||
import '../l10n/app_localizations.dart';
|
||||
import '../utils/platform_info.dart';
|
||||
|
||||
class BackgroundService {
|
||||
bool _initialized = false;
|
||||
String? Function()? _languageOverrideProvider;
|
||||
|
||||
/// Allows the app to expose its current language override (e.g. from
|
||||
/// AppSettingsService) so the foreground notification matches the app UI
|
||||
/// language instead of only the system locale.
|
||||
void setLanguageOverrideProvider(String? Function()? provider) {
|
||||
_languageOverrideProvider = provider;
|
||||
}
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (!PlatformInfo.isAndroid || _initialized) return;
|
||||
@@ -34,13 +45,32 @@ class BackgroundService {
|
||||
}
|
||||
final running = await FlutterForegroundTask.isRunningService;
|
||||
if (running) return;
|
||||
final l10n = await _loadLocalizations();
|
||||
await FlutterForegroundTask.startService(
|
||||
notificationTitle: 'MeshCore running',
|
||||
notificationText: 'Keeping BLE connected',
|
||||
notificationTitle: l10n.background_serviceTitle,
|
||||
notificationText: l10n.background_serviceText,
|
||||
callback: startCallback,
|
||||
);
|
||||
}
|
||||
|
||||
Future<AppLocalizations> _loadLocalizations() async {
|
||||
final supported = AppLocalizations.supportedLocales;
|
||||
final override = _languageOverrideProvider?.call();
|
||||
if (override != null && override.isNotEmpty) {
|
||||
final overrideLocale = Locale(override);
|
||||
final isSupported = supported.any(
|
||||
(l) => l.languageCode == overrideLocale.languageCode,
|
||||
);
|
||||
if (isSupported) {
|
||||
return AppLocalizations.delegate.load(overrideLocale);
|
||||
}
|
||||
}
|
||||
final preferred =
|
||||
WidgetsBinding.instance.platformDispatcher.locales;
|
||||
final match = basicLocaleListResolution(preferred, supported);
|
||||
return AppLocalizations.delegate.load(match);
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
if (!PlatformInfo.isAndroid) return;
|
||||
final running = await FlutterForegroundTask.isRunningService;
|
||||
|
||||
@@ -24,6 +24,26 @@ class LineOfSightSample {
|
||||
});
|
||||
}
|
||||
|
||||
class LineOfSightObstruction {
|
||||
final int sampleIndex;
|
||||
final LatLng point;
|
||||
final double distanceMeters;
|
||||
final double clearanceMeters;
|
||||
final double obstructionMeters;
|
||||
final double terrainMeters;
|
||||
final double lineHeightMeters;
|
||||
|
||||
const LineOfSightObstruction({
|
||||
required this.sampleIndex,
|
||||
required this.point,
|
||||
required this.distanceMeters,
|
||||
required this.clearanceMeters,
|
||||
required this.obstructionMeters,
|
||||
required this.terrainMeters,
|
||||
required this.lineHeightMeters,
|
||||
});
|
||||
}
|
||||
|
||||
class LineOfSightResult {
|
||||
final bool hasData;
|
||||
final bool isClear;
|
||||
@@ -31,6 +51,7 @@ class LineOfSightResult {
|
||||
final double maxObstructionMeters;
|
||||
final double? firstObstructionDistanceMeters;
|
||||
final List<LineOfSightSample> samples;
|
||||
final List<LineOfSightObstruction> obstructions;
|
||||
final String? errorMessage;
|
||||
final double usedKFactor;
|
||||
final double? frequencyMHz;
|
||||
@@ -42,6 +63,7 @@ class LineOfSightResult {
|
||||
required this.maxObstructionMeters,
|
||||
required this.firstObstructionDistanceMeters,
|
||||
required this.samples,
|
||||
required this.obstructions,
|
||||
required this.usedKFactor,
|
||||
this.frequencyMHz,
|
||||
this.errorMessage,
|
||||
@@ -56,7 +78,8 @@ class LineOfSightResult {
|
||||
isClear = false,
|
||||
maxObstructionMeters = 0,
|
||||
firstObstructionDistanceMeters = null,
|
||||
samples = const [];
|
||||
samples = const [],
|
||||
obstructions = const [];
|
||||
}
|
||||
|
||||
class LineOfSightPathSegment {
|
||||
@@ -191,6 +214,7 @@ class LineOfSightService {
|
||||
maxObstructionMeters: 0,
|
||||
firstObstructionDistanceMeters: null,
|
||||
samples: const [],
|
||||
obstructions: const [],
|
||||
usedKFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
@@ -249,7 +273,9 @@ class LineOfSightService {
|
||||
var maxObstructionMeters = 0.0;
|
||||
double? firstObstructionDistanceMeters;
|
||||
final samples = <LineOfSightSample>[];
|
||||
final obstructions = <LineOfSightObstruction>[];
|
||||
var isClear = true;
|
||||
LineOfSightObstruction? clusterWorstObstruction;
|
||||
|
||||
for (int i = 0; i < points.length; i++) {
|
||||
final fraction = points.length == 1 ? 0.0 : i / (points.length - 1);
|
||||
@@ -274,6 +300,23 @@ class LineOfSightService {
|
||||
maxObstructionMeters = obstruction;
|
||||
}
|
||||
firstObstructionDistanceMeters ??= distanceFromStart;
|
||||
final candidate = LineOfSightObstruction(
|
||||
sampleIndex: i,
|
||||
point: points[i],
|
||||
distanceMeters: distanceFromStart,
|
||||
clearanceMeters: clearance,
|
||||
obstructionMeters: obstruction,
|
||||
terrainMeters: terrainHeight,
|
||||
lineHeightMeters: lineHeight,
|
||||
);
|
||||
if (clusterWorstObstruction == null ||
|
||||
candidate.obstructionMeters >
|
||||
clusterWorstObstruction.obstructionMeters) {
|
||||
clusterWorstObstruction = candidate;
|
||||
}
|
||||
} else if (clusterWorstObstruction != null) {
|
||||
obstructions.add(clusterWorstObstruction);
|
||||
clusterWorstObstruction = null;
|
||||
}
|
||||
|
||||
samples.add(
|
||||
@@ -286,6 +329,9 @@ class LineOfSightService {
|
||||
),
|
||||
);
|
||||
}
|
||||
if (clusterWorstObstruction != null) {
|
||||
obstructions.add(clusterWorstObstruction);
|
||||
}
|
||||
|
||||
return LineOfSightResult(
|
||||
hasData: true,
|
||||
@@ -294,6 +340,7 @@ class LineOfSightService {
|
||||
maxObstructionMeters: maxObstructionMeters,
|
||||
firstObstructionDistanceMeters: firstObstructionDistanceMeters,
|
||||
samples: samples,
|
||||
obstructions: obstructions,
|
||||
usedKFactor: kFactor,
|
||||
frequencyMHz: frequencyMHz,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user