From ad4a404ab1dc4e06f36f5cbdc38f67d8d5941587 Mon Sep 17 00:00:00 2001 From: Kush Makkapati Date: Tue, 24 Feb 2026 19:48:16 +0000 Subject: [PATCH 1/9] Fix bug with state not getting set correctly --- gcs/src/redux/middleware/emitters.js | 18 +++++++----------- radio/app/endpoints/states.py | 13 ++++++++----- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/gcs/src/redux/middleware/emitters.js b/gcs/src/redux/middleware/emitters.js index b523f520e..f40cf51a4 100644 --- a/gcs/src/redux/middleware/emitters.js +++ b/gcs/src/redux/middleware/emitters.js @@ -37,12 +37,6 @@ import { setCurrentPage, setIsForwarding, } from "../slices/droneConnectionSlice" -import { - setSimulationStatus, - SimulationStatus, - emitStartSimulation, - emitStopSimulation, -} from "../slices/simulationParamsSlice" import { emitListFiles, emitListLogFiles, @@ -68,6 +62,12 @@ import { emitSetMultipleParams, setParamsWriteProgressModalOpen, } from "../slices/paramsSlice" +import { + emitStartSimulation, + emitStopSimulation, + setSimulationStatus, + SimulationStatus, +} from "../slices/simulationParamsSlice" import { resetMessages } from "../slices/statusTextSlice" export function handleEmitters(socket, store, action) { @@ -146,11 +146,7 @@ export function handleEmitters(socket, store, action) { emitter: emitSetState, callback: () => { store.dispatch(setCurrentPage(action.payload)) - const storeState = store.getState() - const isDroneConnected = storeState.droneConnection.connected - if (isDroneConnected) { - socket.socket.emit("set_state", { state: action.payload }) - } + socket.socket.emit("set_state", { state: action.payload }) }, }, { diff --git a/radio/app/endpoints/states.py b/radio/app/endpoints/states.py index 892892878..e2792bb10 100644 --- a/radio/app/endpoints/states.py +++ b/radio/app/endpoints/states.py @@ -1,3 +1,5 @@ +from logging import getLogger + from pymavlink import mavutil from typing_extensions import TypedDict @@ -5,7 +7,6 @@ from app import socketio from app.utils import ( missingParameterError, - notConnectedError, sendMessage, ) @@ -41,6 +42,8 @@ class SetStateType(TypedDict): "config.rc": ["RC_CHANNELS"], } +logger = getLogger("fgcs") + @socketio.on("set_state") def set_state(data: SetStateType) -> None: @@ -50,16 +53,16 @@ def set_state(data: SetStateType) -> None: Args: data: The form data passed in from the frontend, this contains the state we wish to change to """ - if not droneStatus.drone: - return notConnectedError(action="set the drone state") - # Ensure that a state was actually sent if (newState := data.get("state", None)) is None: return missingParameterError("set_state", "state") + logger.info(f"Changing state to {newState}") + droneStatus.state = newState - droneStatus.drone.logger.info(f"Changing state to {droneStatus.state}") + if not droneStatus.drone: + return # Reset all data streams droneStatus.drone.stopAllDataStreams() From e47a81786c28e5d03ea7c4b0a93f1cd547222691 Mon Sep 17 00:00:00 2001 From: Kush Makkapati Date: Tue, 24 Feb 2026 20:37:10 +0000 Subject: [PATCH 2/9] Add initial missions page conversion for no drone connection --- gcs/src/missions.jsx | 467 +++++++------- gcs/src/redux/middleware/socketMiddleware.js | 200 +++--- radio/app/controllers/missionController.py | 631 +++++++++++-------- radio/app/endpoints/mission.py | 34 +- 4 files changed, 736 insertions(+), 596 deletions(-) diff --git a/gcs/src/missions.jsx b/gcs/src/missions.jsx index 97adabb49..ae25c4fd4 100644 --- a/gcs/src/missions.jsx +++ b/gcs/src/missions.jsx @@ -6,29 +6,27 @@ import { useEffect, useRef, useState } from "react" // 3rd Party Imports -import { useSessionStorage } from "@mantine/hooks" import { ResizableBox } from "react-resizable" import { v4 as uuidv4 } from "uuid" // Custom component and helpers import { - ActionIcon, Button, Divider, Modal, NumberInput, Progress, + Select, Tabs, Tooltip, } from "@mantine/core" -import { IconInfoCircle, IconX } from "@tabler/icons-react" +import { IconInfoCircle } from "@tabler/icons-react" import Layout from "./components/layout" import FenceItemsTable from "./components/missions/fenceItemsTable" import MissionItemsTable from "./components/missions/missionItemsTable" import MissionStatistics from "./components/missions/missionStatistics" import MissionsMapSection from "./components/missions/missionsMap" import RallyItemsTable from "./components/missions/rallyItemsTable" -import NoDroneConnected from "./components/noDroneConnected" import { coordToInt, intToCoord } from "./helpers/dataFormatters" // Redux @@ -43,6 +41,10 @@ import resolveConfig from "tailwindcss/resolveConfig" import tailwindConfig from "../tailwind.config" import UpdatePlannedHomePositionModal from "./components/missions/updatePlannedHomePositionModal" import { showErrorNotification } from "./helpers/notification" +import { + selectAircraftType, + setDroneAircraftType, +} from "./redux/slices/droneInfoSlice" import { emitExportMissionToFile, emitGetCurrentMission, @@ -96,6 +98,7 @@ export default function Missions() { const targetInfo = useSelector(selectTargetInfo) const plannedHomePosition = useSelector(selectPlannedHomePosition) const activeTab = useSelector(selectActiveTab) + const aircraftType = useSelector(selectAircraftType) // Mission items const missionItems = useSelector(selectDrawingMissionItems) @@ -105,12 +108,6 @@ export default function Missions() { const missionProgressModalOpened = useSelector(selectMissionProgressModal) const missionProgressModalData = useSelector(selectMissionProgressData) - // Other states - const [showWarningBanner, setShowWarningBanner] = useSessionStorage({ - key: "showWarningBanner", - defaultValue: true, - }) - // Need to keep a reference to the active tab to avoid stale closures const activeTabRef = useRef(activeTab) const tabsListRef = useRef(null) @@ -345,249 +342,239 @@ export default function Missions() { - {/* Banner to let people know that things are still under development */} - {showWarningBanner && ( -
-

- Missions is still under development so some features are still - missing. If you find any bugs please report them to us. -

- setShowWarningBanner(false)} - variant="transparent" - className="mr-2" +
+
+ {/* Resizable Sidebar */} +
+ } + className="relative bg-falcongrey-800 overflow-y-auto" > - - -
- )} - - {connected ? ( -
-
- {/* Resizable Sidebar */} -
- } - className="relative bg-falcongrey-800 overflow-y-auto" - > -
-
- - - - -
- - - -
- - -
- - - -
-

- Planned home{" "} - - -

- The planned home location is used to approximate - the starting location of the mission. The - dashboard displays the actual home location - used by the drone. -

- - } - > - - - -

- setPlannedHomeLatInput(val)} - onBlur={() => { - if (isInvalidInputNumber(plannedHomeLatInput)) { - setPlannedHomeLatInput( - intToCoord(plannedHomePosition?.lat).toFixed( - coordsFractionDigits, - ), - ) - } - }} - min={-90} - max={90} - step={0.000001} - hideControls - /> - setPlannedHomeLonInput(val)} - onBlur={() => { - if (isInvalidInputNumber(plannedHomeLonInput)) { - setPlannedHomeLonInput( - intToCoord(plannedHomePosition?.lon).toFixed( - coordsFractionDigits, - ), - ) - } +
+
+ {connected ? ( + <> + + + + + ) : ( +