diff --git a/gcs/src/dashboard.jsx b/gcs/src/dashboard.jsx index bccedc62c..741901455 100644 --- a/gcs/src/dashboard.jsx +++ b/gcs/src/dashboard.jsx @@ -35,9 +35,11 @@ import { selectDroneCoords, selectFlightMode, selectGPSRawInt, + selectGPS2RawInt, selectNotificationSound, selectRSSI, soundPlayed, + selectHasSecondaryGps, } from "./redux/slices/droneInfoSlice" import { selectMessages } from "./redux/slices/statusTextSlice" @@ -81,6 +83,10 @@ export default function Dashboard() { const hdopDisplay = hdop != null ? hdop.toFixed(2) : "0.00" const connectedToDrone = useSelector(selectConnectedToDrone) + const gps2 = useSelector(selectGPS2RawInt) + const hasSecondaryGps = useSelector(selectHasSecondaryGps) + + const secondaryGpsFixLabel = GPS_FIX_TYPES[gps2.fixType] // Telemetry panel sizing const [telemetryPanelSize, setTelemetryPanelSize] = useLocalStorage({ @@ -201,6 +207,13 @@ export default function Dashboard() { value={GPS_FIX_TYPES[fixType]} tooltip="GPS fix type" /> + {hasSecondaryGps && ( + } + value={secondaryGpsFixLabel} + tooltip="GPS2 fix type" + /> + )} } value={hdopDisplay} diff --git a/gcs/src/redux/middleware/socketMiddleware.js b/gcs/src/redux/middleware/socketMiddleware.js index cb69edb92..2d5803225 100644 --- a/gcs/src/redux/middleware/socketMiddleware.js +++ b/gcs/src/redux/middleware/socketMiddleware.js @@ -62,6 +62,7 @@ import { setFlightSwVersion, setGpsData, setGpsRawIntData, + setGps2RawIntData, setGuidedModePinData, setHeartbeatData, setHomePosition, @@ -227,6 +228,18 @@ const socketMiddleware = (store) => { store.dispatch(calculateGpsTrackHeadingThunk()) break } + case "GPS2_RAW": { + // MAVLink GPS2_RAW provides 'eph' (HDOP * 100). + const hdop = msg.eph != null ? msg.eph / 100.0 : null + + store.dispatch( + setGps2RawIntData({ + ...msg, + hdop, + }), + ) + break + } case "RC_CHANNELS": // NOTE: UNABLE TO TEST IN SIMULATOR! store.dispatch(setRSSIData(msg.rssi)) diff --git a/gcs/src/redux/slices/droneInfoSlice.js b/gcs/src/redux/slices/droneInfoSlice.js index b5afce67c..a3a4d7edd 100644 --- a/gcs/src/redux/slices/droneInfoSlice.js +++ b/gcs/src/redux/slices/droneInfoSlice.js @@ -59,6 +59,14 @@ const droneInfoSlice = createSlice({ courseOverGround: 0, hdop: 0, }, + gps2RawIntData: { + fixType: 0, + satellitesVisible: 0, + velocity: 0, + courseOverGround: 0, + hdop: 0, + }, + hasSecondaryGps: false, rssi: 0.0, notificationSound: "", aircraftType: 0, // TODO: This should be in local storage but I have no idea how :D, @@ -183,6 +191,20 @@ const droneInfoSlice = createSlice({ state.gpsRawIntData.hdop = action.payload.hdop ?? 0 } }, + setGps2RawIntData: (state, action) => { + if (action.payload !== state.gps2RawIntData) { + state.gps2RawIntData.satellitesVisible = + action.payload.satellites_visible + state.gps2RawIntData.fixType = action.payload.fix_type + state.gps2RawIntData.velocity = action.payload.vel / 100.0 // cm/s to m/s + state.gps2RawIntData.courseOverGround = centiDegToDeg( + action.payload.cog, + ) + state.gps2RawIntData.hdop = action.payload.hdop ?? 0 + + state.hasSecondaryGps = true // Reducer called => gps2 exists + } + }, setOnboardControlSensorsEnabled: (state, action) => { if (action.payload !== state.onboardControlSensorsEnabled) { state.onboardControlSensorsEnabled = action.payload @@ -273,6 +295,8 @@ const droneInfoSlice = createSlice({ selectPrearmEnabled: (state) => state.onboardControlSensorsEnabled & 268435456, selectGPSRawInt: (state) => state.gpsRawIntData, + selectGPS2RawInt: (state) => state.gps2RawIntData, + selectHasSecondaryGps: (state) => state.hasSecondaryGps, selectRSSI: (state) => state.rssi, selectAircraftType: (state) => state.aircraftType, selectBatteryData: (state) => @@ -303,6 +327,7 @@ export const { setAttitudeData, setNavControllerOutput, setGpsRawIntData, + setGps2RawIntData, setBatteryData, setOnboardControlSensorsEnabled, setRSSIData, @@ -417,6 +442,8 @@ export const { selectArmed, selectPrearmEnabled, selectGPSRawInt, + selectGPS2RawInt, + selectHasSecondaryGps, selectRSSI, selectHeading, selectSystemStatus, diff --git a/radio/app/endpoints/states.py b/radio/app/endpoints/states.py index aea2628e2..fb7253559 100644 --- a/radio/app/endpoints/states.py +++ b/radio/app/endpoints/states.py @@ -25,6 +25,7 @@ class SetStateType(TypedDict): "NAV_CONTROLLER_OUTPUT", "SYS_STATUS", "GPS_RAW_INT", + "GPS2_RAW", "RC_CHANNELS", "ESC_TELEMETRY_5_TO_8", "MISSION_CURRENT", diff --git a/radio/tests/test_states.py b/radio/tests/test_states.py index 2ac5d9a5b..3b3ec823d 100644 --- a/radio/tests/test_states.py +++ b/radio/tests/test_states.py @@ -32,8 +32,7 @@ def test_setState_dashboard_state( """Test setting state to dashboard""" socketio_client.emit("set_state", {"state": "dashboard"}) assert len(socketio_client.get_received()) == 0 - # TODO: These values don't seem right to me, they don't include the STATUSTEXT listener? - assert len(droneStatus.drone.message_listeners) == 15 + assert len(droneStatus.drone.message_listeners) == 16 @falcon_test(pass_drone_status=True)