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)