feat: harden geofence and distance diagnostics
This commit is contained in:
193
lib/features/homes/models/geofence_runtime_state.dart
Normal file
193
lib/features/homes/models/geofence_runtime_state.dart
Normal file
@@ -0,0 +1,193 @@
|
||||
class GeofenceRuntimeState {
|
||||
final String? armedHomeId;
|
||||
final DateTime? lastCheckAt;
|
||||
final double? lastDistanceMeters;
|
||||
final String? triggeredHomeId;
|
||||
final DateTime? triggeredAt;
|
||||
final String? lastSuccessHomeId;
|
||||
final DateTime? lastSuccessAt;
|
||||
final String? lastFailureHomeId;
|
||||
final DateTime? lastFailureAt;
|
||||
final String? lastFailureMessage;
|
||||
|
||||
const GeofenceRuntimeState({
|
||||
this.armedHomeId,
|
||||
this.lastCheckAt,
|
||||
this.lastDistanceMeters,
|
||||
this.triggeredHomeId,
|
||||
this.triggeredAt,
|
||||
this.lastSuccessHomeId,
|
||||
this.lastSuccessAt,
|
||||
this.lastFailureHomeId,
|
||||
this.lastFailureAt,
|
||||
this.lastFailureMessage,
|
||||
});
|
||||
|
||||
bool isTriggeredFor(String homeId) =>
|
||||
triggeredHomeId == homeId && triggeredAt != null;
|
||||
|
||||
DateTime? failureAtFor(String homeId) {
|
||||
if (lastFailureHomeId != homeId) return null;
|
||||
return lastFailureAt;
|
||||
}
|
||||
|
||||
String? failureMessageFor(String homeId) {
|
||||
if (lastFailureHomeId != homeId) return null;
|
||||
return lastFailureMessage;
|
||||
}
|
||||
|
||||
GeofenceRuntimeState armForHome(String homeId) {
|
||||
if (armedHomeId == homeId) return this;
|
||||
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: homeId,
|
||||
lastSuccessHomeId: lastSuccessHomeId,
|
||||
lastSuccessAt: lastSuccessAt,
|
||||
lastFailureHomeId: lastFailureHomeId,
|
||||
lastFailureAt: lastFailureAt,
|
||||
lastFailureMessage: lastFailureMessage,
|
||||
);
|
||||
}
|
||||
|
||||
GeofenceRuntimeState disarm() {
|
||||
return GeofenceRuntimeState(
|
||||
lastSuccessHomeId: lastSuccessHomeId,
|
||||
lastSuccessAt: lastSuccessAt,
|
||||
lastFailureHomeId: lastFailureHomeId,
|
||||
lastFailureAt: lastFailureAt,
|
||||
lastFailureMessage: lastFailureMessage,
|
||||
);
|
||||
}
|
||||
|
||||
GeofenceRuntimeState recordInsideHome(
|
||||
String homeId, {
|
||||
required DateTime checkedAt,
|
||||
required double distanceMeters,
|
||||
}) {
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: armedHomeId,
|
||||
lastCheckAt: checkedAt,
|
||||
lastDistanceMeters: distanceMeters,
|
||||
lastSuccessHomeId: lastSuccessHomeId,
|
||||
lastSuccessAt: lastSuccessAt,
|
||||
lastFailureHomeId: lastFailureHomeId == homeId ? null : lastFailureHomeId,
|
||||
lastFailureAt: lastFailureHomeId == homeId ? null : lastFailureAt,
|
||||
lastFailureMessage: lastFailureHomeId == homeId
|
||||
? null
|
||||
: lastFailureMessage,
|
||||
);
|
||||
}
|
||||
|
||||
GeofenceRuntimeState recordOutsideCheck(
|
||||
String homeId, {
|
||||
required DateTime checkedAt,
|
||||
required double distanceMeters,
|
||||
}) {
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: armedHomeId ?? homeId,
|
||||
lastCheckAt: checkedAt,
|
||||
lastDistanceMeters: distanceMeters,
|
||||
triggeredHomeId: triggeredHomeId,
|
||||
triggeredAt: triggeredAt,
|
||||
lastSuccessHomeId: lastSuccessHomeId,
|
||||
lastSuccessAt: lastSuccessAt,
|
||||
lastFailureHomeId: lastFailureHomeId,
|
||||
lastFailureAt: lastFailureAt,
|
||||
lastFailureMessage: lastFailureMessage,
|
||||
);
|
||||
}
|
||||
|
||||
GeofenceRuntimeState recordSuccess(
|
||||
String homeId, {
|
||||
required DateTime triggeredAt,
|
||||
required double distanceMeters,
|
||||
}) {
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: homeId,
|
||||
lastCheckAt: triggeredAt,
|
||||
lastDistanceMeters: distanceMeters,
|
||||
triggeredHomeId: homeId,
|
||||
triggeredAt: triggeredAt,
|
||||
lastSuccessHomeId: homeId,
|
||||
lastSuccessAt: triggeredAt,
|
||||
lastFailureHomeId: lastFailureHomeId == homeId ? null : lastFailureHomeId,
|
||||
lastFailureAt: lastFailureHomeId == homeId ? null : lastFailureAt,
|
||||
lastFailureMessage: lastFailureHomeId == homeId
|
||||
? null
|
||||
: lastFailureMessage,
|
||||
);
|
||||
}
|
||||
|
||||
GeofenceRuntimeState recordFailure(
|
||||
String homeId, {
|
||||
required DateTime failedAt,
|
||||
required double distanceMeters,
|
||||
required String message,
|
||||
}) {
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: homeId,
|
||||
lastCheckAt: failedAt,
|
||||
lastDistanceMeters: distanceMeters,
|
||||
triggeredHomeId: triggeredHomeId == homeId ? null : triggeredHomeId,
|
||||
triggeredAt: triggeredHomeId == homeId ? null : triggeredAt,
|
||||
lastSuccessHomeId: lastSuccessHomeId,
|
||||
lastSuccessAt: lastSuccessAt,
|
||||
lastFailureHomeId: homeId,
|
||||
lastFailureAt: failedAt,
|
||||
lastFailureMessage: message,
|
||||
);
|
||||
}
|
||||
|
||||
GeofenceRuntimeState removeHome(String homeId) {
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: armedHomeId == homeId ? null : armedHomeId,
|
||||
lastCheckAt: armedHomeId == homeId ? null : lastCheckAt,
|
||||
lastDistanceMeters: armedHomeId == homeId ? null : lastDistanceMeters,
|
||||
triggeredHomeId: triggeredHomeId == homeId ? null : triggeredHomeId,
|
||||
triggeredAt: triggeredHomeId == homeId ? null : triggeredAt,
|
||||
lastSuccessHomeId: lastSuccessHomeId == homeId ? null : lastSuccessHomeId,
|
||||
lastSuccessAt: lastSuccessHomeId == homeId ? null : lastSuccessAt,
|
||||
lastFailureHomeId: lastFailureHomeId == homeId ? null : lastFailureHomeId,
|
||||
lastFailureAt: lastFailureHomeId == homeId ? null : lastFailureAt,
|
||||
lastFailureMessage: lastFailureHomeId == homeId
|
||||
? null
|
||||
: lastFailureMessage,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
if (armedHomeId != null) 'armedHomeId': armedHomeId,
|
||||
if (lastCheckAt != null) 'lastCheckAt': lastCheckAt!.millisecondsSinceEpoch,
|
||||
if (lastDistanceMeters != null) 'lastDistanceMeters': lastDistanceMeters,
|
||||
if (triggeredHomeId != null) 'triggeredHomeId': triggeredHomeId,
|
||||
if (triggeredAt != null) 'triggeredAt': triggeredAt!.millisecondsSinceEpoch,
|
||||
if (lastSuccessHomeId != null) 'lastSuccessHomeId': lastSuccessHomeId,
|
||||
if (lastSuccessAt != null)
|
||||
'lastSuccessAt': lastSuccessAt!.millisecondsSinceEpoch,
|
||||
if (lastFailureHomeId != null) 'lastFailureHomeId': lastFailureHomeId,
|
||||
if (lastFailureAt != null)
|
||||
'lastFailureAt': lastFailureAt!.millisecondsSinceEpoch,
|
||||
if (lastFailureMessage != null) 'lastFailureMessage': lastFailureMessage,
|
||||
};
|
||||
|
||||
factory GeofenceRuntimeState.fromJson(Map<String, dynamic> json) {
|
||||
return GeofenceRuntimeState(
|
||||
armedHomeId: json['armedHomeId'] as String?,
|
||||
lastCheckAt: _fromMillis(json['lastCheckAt']),
|
||||
lastDistanceMeters: (json['lastDistanceMeters'] as num?)?.toDouble(),
|
||||
triggeredHomeId: json['triggeredHomeId'] as String?,
|
||||
triggeredAt: _fromMillis(json['triggeredAt']),
|
||||
lastSuccessHomeId: json['lastSuccessHomeId'] as String?,
|
||||
lastSuccessAt: _fromMillis(json['lastSuccessAt']),
|
||||
lastFailureHomeId: json['lastFailureHomeId'] as String?,
|
||||
lastFailureAt: _fromMillis(json['lastFailureAt']),
|
||||
lastFailureMessage: json['lastFailureMessage'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
static DateTime? _fromMillis(Object? value) {
|
||||
final millis = (value as num?)?.toInt();
|
||||
if (millis == null) return null;
|
||||
return DateTime.fromMillisecondsSinceEpoch(millis);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user