diff --git a/gcs/src/components/dashboard/map.jsx b/gcs/src/components/dashboard/map.jsx
index c94d5de90..2f5644026 100644
--- a/gcs/src/components/dashboard/map.jsx
+++ b/gcs/src/components/dashboard/map.jsx
@@ -119,7 +119,7 @@ function MapSectionNonMemo({ passedRef, onDragstart, mapId = "dashboard" }) {
}, [gpsData])
useEffect(() => {
- setFilteredMissionItems(filterMissionItems(missionItems.mission_items))
+ setFilteredMissionItems(filterMissionItems(missionItems.missionItems))
}, [missionItems])
useEffect(() => {
@@ -237,12 +237,12 @@ function MapSectionNonMemo({ passedRef, onDragstart, mapId = "dashboard" }) {
/>
)}
-
+
-
+
{/* Show mission rally point */}
- {missionItems.rally_items.map((item, index) => {
+ {missionItems.rallyItems.map((item, index) => {
return (
{
@@ -58,8 +62,12 @@ export default function Layout({ children, currentPage }) {
if (!connectedToDrone) return
if (currentPage.toLowerCase() == "dashboard") {
- dispatch(emitGetCurrentMissionAll())
dispatch(emitGetHomePosition()) // use actual home position
+
+ if (shouldFetchAllMissionsOnDashboard) {
+ dispatch(emitGetCurrentMissionAll())
+ }
+
if (aircraftTypeString === "Plane") {
dispatch(emitGetLoiterRadius())
}
diff --git a/gcs/src/helpers/notification.js b/gcs/src/helpers/notification.js
index 05192bfae..17722819b 100644
--- a/gcs/src/helpers/notification.js
+++ b/gcs/src/helpers/notification.js
@@ -53,3 +53,28 @@ export function showNotification(title, message) {
...notificationTheme,
})
}
+
+export function showLoadingNotification(title, message) {
+ const id = notifications.show({
+ title: title,
+ message: message,
+ loading: true,
+ autoClose: false,
+ withCloseButton: false,
+ ...notificationTheme,
+ })
+
+ return id
+}
+
+export function closeLoadingNotification(id, title, message) {
+ notifications.update({
+ id: id,
+ title: title,
+ message: message,
+ loading: false,
+ autoClose: 2000,
+ color: tailwindColors.green[600],
+ ...notificationTheme,
+ })
+}
diff --git a/gcs/src/redux/middleware/emitters.js b/gcs/src/redux/middleware/emitters.js
index 03b6cbd9d..6ebeda055 100644
--- a/gcs/src/redux/middleware/emitters.js
+++ b/gcs/src/redux/middleware/emitters.js
@@ -22,6 +22,8 @@ import {
emitGetTargetInfo,
emitImportMissionFromFile,
emitWriteCurrentMission,
+ setShouldFetchAllMissionsOnDashboard,
+ showDashboardMissionFetchingNotificationThunk,
} from "../slices/missionSlice"
import {
emitRebootAutopilot,
@@ -70,7 +72,10 @@ export function handleEmitters(socket, store, action) {
},
{
emitter: emitGetCurrentMissionAll,
- callback: () => socket.socket.emit("get_current_mission_all"),
+ callback: () => {
+ socket.socket.emit("get_current_mission_all")
+ store.dispatch(showDashboardMissionFetchingNotificationThunk())
+ },
},
{
emitter: emitSetLoiterRadius,
@@ -142,6 +147,7 @@ export function handleEmitters(socket, store, action) {
type: action.payload.type,
items: action.payload.items,
})
+ store.dispatch(setShouldFetchAllMissionsOnDashboard(true))
},
},
{
diff --git a/gcs/src/redux/middleware/socketMiddleware.js b/gcs/src/redux/middleware/socketMiddleware.js
index a5601d7a2..90671471d 100644
--- a/gcs/src/redux/middleware/socketMiddleware.js
+++ b/gcs/src/redux/middleware/socketMiddleware.js
@@ -10,10 +10,7 @@ import {
// drone actions
import {
emitGetComPorts,
- emitGetHomePosition,
- emitGetLoiterRadius,
emitIsConnectedToDrone,
- emitSetState,
setComPorts,
setConnected,
setConnecting,
@@ -46,6 +43,7 @@ import {
} from "../slices/droneInfoSlice"
import {
addIdToItem,
+ closeDashboardMissionFetchingNotificationThunk,
setCurrentMission,
setCurrentMissionItems,
setDrawingFenceItems,
@@ -53,6 +51,7 @@ import {
setDrawingRallyItems,
setMissionProgressData,
setMissionProgressModal,
+ setShouldFetchAllMissionsOnDashboard,
setTargetInfo,
setUnwrittenChanges,
setUpdatePlannedHomePositionFromLoadData,
@@ -264,19 +263,10 @@ const socketMiddleware = (store) => {
store.dispatch(setConnecting(false))
store.dispatch(setConnectionModal(false))
- const currentPage = store.getState().droneConnection.currentPage
- store.dispatch(emitSetState(currentPage))
-
- if (["dashboard", "missions"].includes(currentPage)) {
- store.dispatch(emitGetHomePosition()) // fetch the actual home position of the drone
- if (msg.aircraft_type === 1) {
- store.dispatch(emitGetLoiterRadius())
- }
- }
-
store.dispatch(setGuidedModePinData({ lat: 0, lon: 0, alt: 0 }))
store.dispatch(setRebootData({}))
store.dispatch(setAutoPilotRebootModalOpen(false))
+ store.dispatch(setShouldFetchAllMissionsOnDashboard(true))
})
// Link stats
@@ -412,7 +402,19 @@ const socketMiddleware = (store) => {
socket.socket.on(
MissionSpecificSocketEvents.onCurrentMissionAll,
(msg) => {
- store.dispatch(setCurrentMissionItems(msg))
+ if (!msg.success) {
+ store.dispatch(queueErrorNotification(msg.message))
+ } else {
+ store.dispatch(
+ setCurrentMissionItems({
+ missionItems: msg.mission_items,
+ fenceItems: msg.fence_items,
+ rallyItems: msg.rally_items,
+ }),
+ )
+ store.dispatch(setShouldFetchAllMissionsOnDashboard(false))
+ }
+ store.dispatch(closeDashboardMissionFetchingNotificationThunk())
},
)
diff --git a/gcs/src/redux/slices/missionSlice.js b/gcs/src/redux/slices/missionSlice.js
index c1602b459..bfe1b2ddd 100644
--- a/gcs/src/redux/slices/missionSlice.js
+++ b/gcs/src/redux/slices/missionSlice.js
@@ -3,6 +3,10 @@ import { v4 as uuidv4 } from "uuid"
import { coordToInt } from "../../helpers/dataFormatters"
import { isGlobalFrameHomeCommand } from "../../helpers/filterMissions"
import { MAV_FRAME_LIST } from "../../helpers/mavlinkConstants"
+import {
+ closeLoadingNotification,
+ showLoadingNotification,
+} from "../../helpers/notification"
const missionInfoSlice = createSlice({
name: "missionInfo",
@@ -13,10 +17,9 @@ const missionInfoSlice = createSlice({
seq: 0,
},
currentMissionItems: {
- // These should be camelCase etc but its easier to keep it as snake_case
- mission_items: [],
- fence_items: [],
- rally_items: [],
+ missionItems: [],
+ fenceItems: [],
+ rallyItems: [],
},
drawingItems: {
// This is for the missions page, used locally and then will update currentMissionItems on save
@@ -61,6 +64,8 @@ const missionInfoSlice = createSlice({
gpsCoords: { lat: 0, lng: 0 },
markerId: null,
},
+ shouldFetchAllMissionsOnDashboard: true, // bool so that the dashboard can refresh its data when switched to if needed
+ dashboardMissionFetchingNotificationId: null,
},
reducers: {
setCurrentMission: (state, action) => {
@@ -394,6 +399,15 @@ const missionInfoSlice = createSlice({
position: { x: x, y: y },
}
},
+ setShouldFetchAllMissionsOnDashboard: (state, action) => {
+ if (action.payload === state.shouldFetchAllMissionsOnDashboard) return
+ state.shouldFetchAllMissionsOnDashboard = action.payload
+ },
+ setDashboardMissionFetchingNotificationId: (state, action) => {
+ if (action.payload === state.dashboardMissionFetchingNotificationId)
+ return
+ state.dashboardMissionFetchingNotificationId = action.payload
+ },
// Emits
emitGetTargetInfo: () => {},
@@ -422,6 +436,10 @@ const missionInfoSlice = createSlice({
selectMissionProgressData: (state) => state.missionProgressData,
selectActiveTab: (state) => state.activeTab,
selectContextMenu: (state) => state.contextMenu,
+ selectShouldFetchAllMissionsOnDashboard: (state) =>
+ state.shouldFetchAllMissionsOnDashboard,
+ selectDashboardMissionFetchingNotificationId: (state) =>
+ state.dashboardMissionFetchingNotificationId,
},
})
@@ -491,6 +509,28 @@ export const setPlannedHomePositionToDronesHomePositionThunk =
}
}
+export const showDashboardMissionFetchingNotificationThunk =
+ () => (dispatch) => {
+ const notificationId = showLoadingNotification(
+ "Fetching the mission",
+ "Fetching the mission from the drone",
+ )
+ dispatch(setDashboardMissionFetchingNotificationId(notificationId))
+ }
+
+export const closeDashboardMissionFetchingNotificationThunk =
+ () => (dispatch, getState) => {
+ const { dashboardMissionFetchingNotificationId } = getState().missionInfo
+ if (dashboardMissionFetchingNotificationId) {
+ closeLoadingNotification(
+ dashboardMissionFetchingNotificationId,
+ "Mission fetched",
+ "Successfully fetched the mission from the drone",
+ )
+ }
+ dispatch(setDashboardMissionFetchingNotificationId(null))
+ }
+
export const getFrameKey = (frame) =>
parseInt(
Object.keys(MAV_FRAME_LIST).find((key) => MAV_FRAME_LIST[key] == frame),
@@ -534,6 +574,8 @@ export const {
selectMissionProgressData,
selectActiveTab,
selectContextMenu,
+ selectShouldFetchAllMissionsOnDashboard,
+ selectDashboardMissionFetchingNotificationId,
} = missionInfoSlice.selectors
export const {
@@ -565,6 +607,8 @@ export const {
emitWriteCurrentMission,
emitImportMissionFromFile,
emitExportMissionToFile,
+ setShouldFetchAllMissionsOnDashboard,
+ setDashboardMissionFetchingNotificationId,
emitControlMission,
} = missionInfoSlice.actions
diff --git a/radio/app/controllers/missionController.py b/radio/app/controllers/missionController.py
index c6139aa3a..0e1528da0 100644
--- a/radio/app/controllers/missionController.py
+++ b/radio/app/controllers/missionController.py
@@ -135,22 +135,22 @@ def getCurrentMissionAll(self) -> Response:
rally_items: List[Any] = []
_mission_items = self.getMissionItems(mission_type=TYPE_MISSION)
- if not _mission_items.get("success"):
- self.drone.logger.warning(_mission_items.get("message"))
- else:
+ if _mission_items.get("success"):
mission_items = _mission_items.get("data", [])
+ else:
+ return _mission_items
_fence_items = self.getMissionItems(mission_type=TYPE_FENCE)
- if not _fence_items.get("success"):
- self.drone.logger.warning(_fence_items.get("message"))
- else:
+ if _fence_items.get("success"):
fence_items = _fence_items.get("data", [])
+ else:
+ return _fence_items
_rally_items = self.getMissionItems(mission_type=TYPE_RALLY)
- if not _rally_items.get("success"):
- self.drone.logger.warning(_rally_items.get("message"))
- else:
+ if _rally_items.get("success"):
rally_items = _rally_items.get("data", [])
+ else:
+ return _rally_items
return {
"success": True,
diff --git a/radio/app/endpoints/mission.py b/radio/app/endpoints/mission.py
index 4949a70f2..ef549d099 100644
--- a/radio/app/endpoints/mission.py
+++ b/radio/app/endpoints/mission.py
@@ -107,6 +107,10 @@ def getCurrentMissionAll() -> None:
result = droneStatus.drone.missionController.getCurrentMissionAll()
+ if not result.get("success"):
+ socketio.emit("current_mission_all", result)
+ return
+
data: dict[str, Any] = result.get("data", {})
if not isinstance(data, dict):
data = {}
@@ -114,6 +118,7 @@ def getCurrentMissionAll() -> None:
socketio.emit(
"current_mission_all",
{
+ "success": True,
"mission_items": data.get("mission_items", []),
"fence_items": data.get("fence_items", []),
"rally_items": data.get("rally_items", []),
diff --git a/radio/tests/mission_test_files/test_getCurrentMission_correctState_result.json b/radio/tests/mission_test_files/test_getCurrentMission_correctState_result.json
index 9395ccca4..d0ef6a991 100644
--- a/radio/tests/mission_test_files/test_getCurrentMission_correctState_result.json
+++ b/radio/tests/mission_test_files/test_getCurrentMission_correctState_result.json
@@ -1,4 +1,5 @@
{
+ "success": true,
"mission_items": [
{
"autocontinue": 1,