Files
PilotVault/Fly App/lib/ui/fly/modes/waypoints/waypoint_start.dart
T
tajniak81andClaude Opus 5.5 9cca65019f Retry a timed-out waypoint upload and wait for the route to be ready
On the Mavic Pro in the simulator a waypoint mission failed with "Execution
of this process has timed out". The bridge now resends a timed-out upload
with retryUploadMission (up to 3 times) and only reports the upload done once
the operator is READY_TO_EXECUTE, and the error now says whether the upload
or the start failed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 09:25:28 +02:00

49 lines
2.2 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:math' as math;
import 'package:flutter/material.dart';
import '../../../../fly/hud_geometry.dart';
import '../../../../fly/modes/waypoint_mission.dart';
import '../../../../fly/safety_gate.dart';
import '../../dialogs/slide_to_confirm.dart';
/// Starts a waypoint mission the GO 4 way (plan P7): the pre-start check —
/// the [SafetyGate]'s mission checks against the aircraft's limits, the RTH
/// altitude, the route summary — then slide to start. The gate re-checks,
/// uploads (the run panel shows the progress) and starts.
Future<void> startWaypointFlow(
BuildContext context, {
required SafetyGate gate,
required WaypointMissionSpec spec,
required void Function(String label, Object error) onError,
}) async {
final MissionLimits limits = await gate.missionLimits();
if (!context.mounted) return;
final List<GateCheck> checks = gate.checkWaypointStart(spec, limits);
final double top = spec.points.fold(0.0, (double h, WaypointSpec p) => math.max(h, p.altitude));
final int rth = (gate.model.aircraft.goHomeHeight ?? 60).round().clamp(SafetyGate.minRthHeight, SafetyGate.maxRthHeight);
final String length = spec.length >= 1000 ? '${(spec.length / 1000).toStringAsFixed(2)} km' : '${spec.length.round()} m';
final SlideResult? r = await showSlideToConfirm(
context,
SlideConfirmSpec(
icon: 'route',
title: 'Start "${spec.name}"',
description: '${spec.points.length} waypoints · $length · about ${formatDuration(spec.estimatedSeconds)}'
'${spec.repeatTimes > 1 ? ' · ${spec.repeatTimes}×' : ''}. '
'Highest waypoint ${top.round()} m. When finished: ${spec.finishAction.label.toLowerCase()}. '
'Pause or Stop at any time, or press the remote\'s pause button.',
sliderLabel: 'Slide to start',
checks: checks,
number: SlideNumber(label: 'RTH altitude', initial: rth, min: SafetyGate.minRthHeight, max: SafetyGate.maxRthHeight),
),
);
if (r == null) return;
bool uploaded = false;
try {
await gate.startWaypointMission(spec, limits: limits, rthHeight: r.number, onUploaded: () => uploaded = true);
} catch (e) {
onError(uploaded ? 'Waypoint start' : 'Waypoint upload', e);
}
}