mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 08:20:36 +00:00
70 lines
2.1 KiB
Dart
70 lines
2.1 KiB
Dart
import 'dart:typed_data';
|
|
|
|
class FastGpsPacket {
|
|
static const int magic = 0x47; // 'G'
|
|
static const int _payloadLength = 19;
|
|
// Store coordinates in microdegrees. This preserves sub-meter precision,
|
|
// which comfortably satisfies the meter-accuracy requirement.
|
|
static const double coordinateScale = 1e6;
|
|
|
|
final String senderKey6;
|
|
final double latitude;
|
|
final double longitude;
|
|
final int timestampSeconds;
|
|
|
|
const FastGpsPacket({
|
|
required this.senderKey6,
|
|
required this.latitude,
|
|
required this.longitude,
|
|
required this.timestampSeconds,
|
|
});
|
|
|
|
static bool isFastGpsBinary(Uint8List payload) =>
|
|
payload.length == _payloadLength && payload[0] == magic;
|
|
|
|
static FastGpsPacket? tryParseBinary(Uint8List payload) {
|
|
if (!isFastGpsBinary(payload)) return null;
|
|
|
|
final key6 = payload
|
|
.sublist(1, 7)
|
|
.map((b) => b.toRadixString(16).padLeft(2, '0'))
|
|
.join();
|
|
final data = ByteData.sublistView(payload);
|
|
final latitude = data.getInt32(7, Endian.little) / coordinateScale;
|
|
final longitude = data.getInt32(11, Endian.little) / coordinateScale;
|
|
final timestampSeconds = data.getUint32(15, Endian.little);
|
|
|
|
if (!_isValidCoordinate(latitude, longitude)) {
|
|
return null;
|
|
}
|
|
|
|
return FastGpsPacket(
|
|
senderKey6: key6,
|
|
latitude: latitude,
|
|
longitude: longitude,
|
|
timestampSeconds: timestampSeconds,
|
|
);
|
|
}
|
|
|
|
Uint8List encodeBinary() {
|
|
final out = Uint8List(_payloadLength);
|
|
final data = ByteData.sublistView(out);
|
|
out[0] = magic;
|
|
for (var i = 0; i < 6; i++) {
|
|
out[1 + i] = int.parse(senderKey6.substring(i * 2, i * 2 + 2), radix: 16);
|
|
}
|
|
data.setInt32(7, (latitude * coordinateScale).round(), Endian.little);
|
|
data.setInt32(11, (longitude * coordinateScale).round(), Endian.little);
|
|
data.setUint32(15, timestampSeconds, Endian.little);
|
|
return out;
|
|
}
|
|
|
|
static bool _isValidCoordinate(double latitude, double longitude) {
|
|
if (!latitude.isFinite || !longitude.isFinite) return false;
|
|
return latitude >= -90.0 &&
|
|
latitude <= 90.0 &&
|
|
longitude >= -180.0 &&
|
|
longitude <= 180.0;
|
|
}
|
|
}
|