You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
meshcore-client/lib/helpers/time_anomaly.dart

47 lines
1.7 KiB

/// Ingest time-anomaly detection (#285, child of #280).
///
/// A received message carries the SENDER's claimed timestamp in its payload;
/// nothing guarantees that clock is sane. These helpers compare the claimed
/// time against the local arrival time so the ingest log can prove, after the
/// fact, whether an odd date came in on the wire.
library;
/// Claimed-vs-arrival gap beyond which a received message is logged as a
/// time anomaly. Generous enough for mesh store-and-forward delays and
/// timezone-free radio clocks; months-off RTCs blow well past it.
const Duration rxTimeAnomalyThreshold = Duration(hours: 24);
/// True when the sender-claimed [claimed] time is further than [threshold]
/// from the local [arrival] time in either direction.
bool isRxTimeAnomaly(
DateTime arrival,
DateTime claimed, {
Duration threshold = rxTimeAnomalyThreshold,
}) {
return claimed.difference(arrival).abs() > threshold;
}
/// Compact human delta of claimed relative to arrival, e.g. `-64d5h` (claimed
/// 64 days in the past) or `+3m` (claimed 3 minutes ahead). `0s` when equal.
String formatRxTimeDelta(DateTime arrival, DateTime claimed) {
final delta = claimed.difference(arrival);
if (delta == Duration.zero) return '0s';
final sign = delta.isNegative ? '-' : '+';
var d = delta.abs();
final parts = <String>[];
if (d.inDays > 0) {
parts.add('${d.inDays}d');
d -= Duration(days: d.inDays);
}
if (d.inHours > 0) {
parts.add('${d.inHours}h');
d -= Duration(hours: d.inHours);
}
if (parts.length < 2 && d.inMinutes > 0) {
parts.add('${d.inMinutes}m');
d -= Duration(minutes: d.inMinutes);
}
if (parts.isEmpty) parts.add('${d.inSeconds}s');
return '$sign${parts.take(2).join()}';
}

Powered by TurnKey Linux.