/// Ein Drohnen-Profil mit Flugleistungsdaten (Architektur-Doku 3.5/7.3): /// FC-Typ ist bewusst NICHT Teil dieses MVP-Profils (nur iNAV/MSP im /// Scope, siehe CLAUDE.md) - anders als im HTML-Demonstrator, der bereits /// auf MAVLink vorbereitet. class DroneProfile { const DroneProfile({ this.id, required this.name, required this.minSpeed, required this.cruiseSpeed, required this.maxSpeed, required this.minTurnRadius, required this.loiterRadius, required this.catchRadius, required this.maxClimbRate, required this.maxDescentRate, required this.maxRangeM, required this.maxEnduranceMin, required this.maxAltitudeM, this.gpsSatGreenMin = defaultGpsSatGreenMin, this.gpsSatRedMin = defaultGpsSatRedMin, this.hdopGreenMax = defaultHdopGreenMax, this.hdopRedMax = defaultHdopRedMax, this.currentGreenMaxA = defaultCurrentGreenMaxA, this.currentRedMaxA = defaultCurrentRedMaxA, this.batteryVoltageGreenMinV = defaultBatteryVoltageGreenMinV, this.batteryVoltageRedMinV = defaultBatteryVoltageRedMinV, this.rxQualityGreenMin = defaultRxQualityGreenMin, this.rxQualityRedMin = defaultRxQualityRedMin, this.rxSnrGreenMinDb = defaultRxSnrGreenMinDb, this.rxSnrRedMinDb = defaultRxSnrRedMinDb, }); /// Null fuer ein noch nicht gespeichertes (neu angelegtes) Profil. final int? id; final String name; final double minSpeed; final double cruiseSpeed; final double maxSpeed; final double minTurnRadius; final double loiterRadius; final double catchRadius; final double maxClimbRate; final double maxDescentRate; final double maxRangeM; final double maxEnduranceMin; final double maxAltitudeM; /// Ampel-Schwellwerte fuer die farbcodierten Telemetriefelder im /// Drohnen-Status-Menue (Doku: "Schwellwerte fuer die Ampel-Kodierung im /// Drohnenprofil anlegen", siehe domain/telemetry/telemetry_field_status.dart) /// - je Feld eine Gruen- und eine Rot-Schwelle, dazwischen gilt gelb. /// *Max/*GreenMax bei Feldern, bei denen ein NIEDRIGER Wert gut ist (HDOP), /// *Min/*GreenMin bei Feldern, bei denen ein HOHER Wert gut ist (alle /// anderen). Default-Werte als statische Konstanten (statt nur inline im /// Konstruktor), damit sie auch als Fallback beim Import aelterer, noch /// ohne diese Felder exportierter Profile dienen koennen (siehe /// drone_share_codec.dart). final double gpsSatGreenMin; final double gpsSatRedMin; final double hdopGreenMax; final double hdopRedMax; final double currentGreenMaxA; final double currentRedMaxA; final double batteryVoltageGreenMinV; final double batteryVoltageRedMinV; final double rxQualityGreenMin; final double rxQualityRedMin; final double rxSnrGreenMinDb; final double rxSnrRedMinDb; static const defaultGpsSatGreenMin = 8.0; static const defaultGpsSatRedMin = 6.0; static const defaultHdopGreenMax = 2.0; static const defaultHdopRedMax = 5.0; static const defaultCurrentGreenMaxA = 20.0; static const defaultCurrentRedMaxA = 30.0; static const defaultBatteryVoltageGreenMinV = 20.4; static const defaultBatteryVoltageRedMinV = 19.2; static const defaultRxQualityGreenMin = 70.0; static const defaultRxQualityRedMin = 50.0; static const defaultRxSnrGreenMinDb = 0.0; static const defaultRxSnrRedMinDb = -10.0; /// T1 Ranger (Heewing) - Standardprofil (Doku 3.5), analog DEFAULT_DRONE /// im HTML-Demonstrator. static const _t1RangerName = 'T1 Ranger'; factory DroneProfile.t1Ranger() => const DroneProfile( name: _t1RangerName, minSpeed: 13, cruiseSpeed: 15, maxSpeed: 25, minTurnRadius: 35, loiterRadius: 100, catchRadius: 60, maxClimbRate: 5, maxDescentRate: 6, maxRangeM: 15000, maxEnduranceMin: 45, maxAltitudeM: 2000, ); /// Einzeilige Zusammenfassung fuer die Profilliste (Doku 3.5), analog /// droneSummary() im HTML-Demonstrator. String get summary { final rangeKm = (maxRangeM / 100).round() / 10; return '$minSpeed–$cruiseSpeed–$maxSpeed m/s · R${minTurnRadius.round()}m · ' '↑${maxClimbRate.round()}/↓${maxDescentRate.round()} m/s · ${rangeKm}km · ' '${maxEnduranceMin.round()}min · ceil ${maxAltitudeM.round()}m'; } DroneProfile copyWith({ int? id, String? name, double? minSpeed, double? cruiseSpeed, double? maxSpeed, double? minTurnRadius, double? loiterRadius, double? catchRadius, double? maxClimbRate, double? maxDescentRate, double? maxRangeM, double? maxEnduranceMin, double? maxAltitudeM, double? gpsSatGreenMin, double? gpsSatRedMin, double? hdopGreenMax, double? hdopRedMax, double? currentGreenMaxA, double? currentRedMaxA, double? batteryVoltageGreenMinV, double? batteryVoltageRedMinV, double? rxQualityGreenMin, double? rxQualityRedMin, double? rxSnrGreenMinDb, double? rxSnrRedMinDb, }) { return DroneProfile( id: id ?? this.id, name: name ?? this.name, minSpeed: minSpeed ?? this.minSpeed, cruiseSpeed: cruiseSpeed ?? this.cruiseSpeed, maxSpeed: maxSpeed ?? this.maxSpeed, minTurnRadius: minTurnRadius ?? this.minTurnRadius, loiterRadius: loiterRadius ?? this.loiterRadius, catchRadius: catchRadius ?? this.catchRadius, maxClimbRate: maxClimbRate ?? this.maxClimbRate, maxDescentRate: maxDescentRate ?? this.maxDescentRate, maxRangeM: maxRangeM ?? this.maxRangeM, maxEnduranceMin: maxEnduranceMin ?? this.maxEnduranceMin, maxAltitudeM: maxAltitudeM ?? this.maxAltitudeM, gpsSatGreenMin: gpsSatGreenMin ?? this.gpsSatGreenMin, gpsSatRedMin: gpsSatRedMin ?? this.gpsSatRedMin, hdopGreenMax: hdopGreenMax ?? this.hdopGreenMax, hdopRedMax: hdopRedMax ?? this.hdopRedMax, currentGreenMaxA: currentGreenMaxA ?? this.currentGreenMaxA, currentRedMaxA: currentRedMaxA ?? this.currentRedMaxA, batteryVoltageGreenMinV: batteryVoltageGreenMinV ?? this.batteryVoltageGreenMinV, batteryVoltageRedMinV: batteryVoltageRedMinV ?? this.batteryVoltageRedMinV, rxQualityGreenMin: rxQualityGreenMin ?? this.rxQualityGreenMin, rxQualityRedMin: rxQualityRedMin ?? this.rxQualityRedMin, rxSnrGreenMinDb: rxSnrGreenMinDb ?? this.rxSnrGreenMinDb, rxSnrRedMinDb: rxSnrRedMinDb ?? this.rxSnrRedMinDb, ); } }