mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
feat: Enhance SAR message handling with improved parsing and object marker generation
This commit is contained in:
@@ -117,6 +117,7 @@ class SampleDataGenerator {
|
||||
int foundPersonCount = 2,
|
||||
int fireCount = 1,
|
||||
int stagingCount = 1,
|
||||
int objectCount = 1,
|
||||
}) {
|
||||
final messages = <Message>[];
|
||||
final now = DateTime.now();
|
||||
@@ -209,14 +210,53 @@ class SampleDataGenerator {
|
||||
messageId++;
|
||||
}
|
||||
|
||||
// Generate object markers
|
||||
for (int i = 0; i < objectCount; i++) {
|
||||
final latOffset = (_random.nextDouble() - 0.5) * 0.015;
|
||||
final lonOffset = (_random.nextDouble() - 0.5) * 0.015;
|
||||
final lat = centerLocation.latitude + latOffset;
|
||||
final lon = centerLocation.longitude + lonOffset;
|
||||
|
||||
final senderKey = Uint8List.fromList(
|
||||
List.generate(32, (_) => _random.nextInt(256)),
|
||||
);
|
||||
|
||||
final timestamp = now.subtract(Duration(minutes: 40 + i * 5));
|
||||
final notes = [
|
||||
' Backpack found - blue color',
|
||||
' Vehicle abandoned - check for owner',
|
||||
' Camping equipment discovered',
|
||||
' Trail marker found off-path',
|
||||
];
|
||||
|
||||
messages.add(Message(
|
||||
id: 'sample_object_$messageId',
|
||||
messageType: MessageType.contact,
|
||||
senderPublicKeyPrefix: senderKey.sublist(0, 6),
|
||||
pathLen: 1,
|
||||
textType: MessageTextType.plain,
|
||||
senderTimestamp: timestamp.millisecondsSinceEpoch ~/ 1000,
|
||||
text: 'S:📦:${lat.toStringAsFixed(4)},${lon.toStringAsFixed(4)}${notes[i % notes.length]}',
|
||||
receivedAt: timestamp,
|
||||
isSarMarker: true,
|
||||
sarMarkerType: SarMarkerType.object,
|
||||
sarGpsCoordinates: LatLng(lat, lon),
|
||||
senderName: 'Sample Searcher',
|
||||
));
|
||||
messageId++;
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
/// Generate sample channel messages for public channels
|
||||
static List<Message> generateChannelMessages({
|
||||
LatLng? centerLocation,
|
||||
int generalChannelMessages = 8,
|
||||
int emergencyChannelMessages = 5,
|
||||
}) {
|
||||
// Use provided location or default to Ljubljana, Slovenia
|
||||
final center = centerLocation ?? const LatLng(46.0569, 14.5058);
|
||||
final messages = <Message>[];
|
||||
final now = DateTime.now();
|
||||
int messageId = 1000; // Start with high ID to avoid conflicts
|
||||
@@ -238,16 +278,17 @@ class SampleDataGenerator {
|
||||
];
|
||||
|
||||
// Sample messages for Emergency channel (index 1)
|
||||
// Mix regular messages and SAR markers
|
||||
final emergencyMessages = [
|
||||
'URGENT: Medical assistance needed at sector 4',
|
||||
'Found person - requesting immediate evac',
|
||||
'S:🧑:${center.latitude.toStringAsFixed(4)},${(center.longitude + 0.005).toStringAsFixed(4)} Adult male, conscious',
|
||||
'Fire spotted - coordinates incoming',
|
||||
'Team member injured - sending location',
|
||||
'S:🔥:${(center.latitude + 0.008).toStringAsFixed(4)},${(center.longitude + 0.003).toStringAsFixed(4)} Spreading rapidly!',
|
||||
'PRIORITY: Need helicopter support',
|
||||
'Medical team en route to your location',
|
||||
'Evac helicopter ETA 10 minutes',
|
||||
'Emergency resolved - all clear',
|
||||
'Casualties: 1 minor injury, being treated',
|
||||
'S:🏕️:${(center.latitude - 0.002).toStringAsFixed(4)},${(center.longitude - 0.004).toStringAsFixed(4)} Emergency staging area',
|
||||
'Emergency services notified and responding',
|
||||
];
|
||||
|
||||
|
||||
@@ -9,14 +9,19 @@ import '../models/message.dart';
|
||||
/// S:🔥:40.7128,-74.0060
|
||||
/// S:🏕️:34.0522,-118.2437
|
||||
class SarMessageParser {
|
||||
// Updated regex to allow optional notes after coordinates
|
||||
// Captures: emoji (one or more non-colon chars), latitude, longitude
|
||||
// Note: Emojis are multi-byte characters, so we use [^:]+ instead of .
|
||||
static final RegExp _sarPattern = RegExp(
|
||||
r'^S:(.):(-?\d+\.?\d*),(-?\d+\.?\d*)$',
|
||||
r'^S:([^:]+):(-?\d+\.?\d*),(-?\d+\.?\d*)',
|
||||
multiLine: false,
|
||||
);
|
||||
|
||||
/// Check if a message is a SAR marker message
|
||||
static bool isSarMessage(String text) {
|
||||
return text.trim().startsWith('S:') && _sarPattern.hasMatch(text.trim());
|
||||
// Extract just the first line for matching
|
||||
final firstLine = text.trim().split('\n').first;
|
||||
return firstLine.startsWith('S:') && _sarPattern.hasMatch(firstLine);
|
||||
}
|
||||
|
||||
/// Parse a SAR message and extract marker information
|
||||
@@ -25,7 +30,9 @@ class SarMessageParser {
|
||||
final trimmed = text.trim();
|
||||
if (!trimmed.startsWith('S:')) return null;
|
||||
|
||||
final match = _sarPattern.firstMatch(trimmed);
|
||||
// Extract first line (actual SAR marker)
|
||||
final firstLine = trimmed.split('\n').first;
|
||||
final match = _sarPattern.firstMatch(firstLine);
|
||||
if (match == null) return null;
|
||||
|
||||
try {
|
||||
@@ -40,10 +47,24 @@ class SarMessageParser {
|
||||
final markerType = SarMarkerType.fromEmoji(emoji);
|
||||
final location = LatLng(latitude, longitude);
|
||||
|
||||
// Extract notes if present (everything after coordinates on first line, or subsequent lines)
|
||||
String? notes;
|
||||
final coordsEnd = match.end;
|
||||
if (coordsEnd < firstLine.length) {
|
||||
// Notes on same line after coordinates
|
||||
notes = firstLine.substring(coordsEnd).trim();
|
||||
}
|
||||
// Check for multi-line notes
|
||||
final additionalNotes = extractNotes(text);
|
||||
if (additionalNotes != null) {
|
||||
notes = notes != null ? '$notes\n$additionalNotes' : additionalNotes;
|
||||
}
|
||||
|
||||
return SarMarkerInfo(
|
||||
type: markerType,
|
||||
location: location,
|
||||
emoji: emoji,
|
||||
notes: notes,
|
||||
);
|
||||
} catch (e) {
|
||||
return null;
|
||||
@@ -139,15 +160,17 @@ class SarMarkerInfo {
|
||||
final SarMarkerType type;
|
||||
final LatLng location;
|
||||
final String emoji;
|
||||
final String? notes;
|
||||
|
||||
SarMarkerInfo({
|
||||
required this.type,
|
||||
required this.location,
|
||||
required this.emoji,
|
||||
this.notes,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SarMarkerInfo(type: ${type.displayName}, location: $location)';
|
||||
return 'SarMarkerInfo(type: ${type.displayName}, location: $location, notes: $notes)';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user