diff --git a/DashboardCore/src/main/java/com/acmerobotics/dashboard/RobotStatus.java b/DashboardCore/src/main/java/com/acmerobotics/dashboard/RobotStatus.java index cf9fe3513..0490814f6 100644 --- a/DashboardCore/src/main/java/com/acmerobotics/dashboard/RobotStatus.java +++ b/DashboardCore/src/main/java/com/acmerobotics/dashboard/RobotStatus.java @@ -20,18 +20,20 @@ public enum OpModeStatus { private OpModeStatus activeOpModeStatus; private String warningMessage; private String errorMessage; + private double batteryVoltage; /** * Creates a status object with the default values. */ public RobotStatus(boolean enabled, boolean available, String activeOpMode, OpModeStatus activeOpModeStatus, String warningMessage, - String errorMessage) { + String errorMessage, double batteryVoltage) { this.enabled = enabled; this.available = available; this.activeOpMode = activeOpMode; this.activeOpModeStatus = activeOpModeStatus; this.warningMessage = warningMessage; this.errorMessage = errorMessage; + this.batteryVoltage = batteryVoltage; } } diff --git a/DashboardCore/src/test/java/com/acmerobotics/dashboard/TestDashboardInstance.java b/DashboardCore/src/test/java/com/acmerobotics/dashboard/TestDashboardInstance.java index 7b1061069..27716b7af 100644 --- a/DashboardCore/src/test/java/com/acmerobotics/dashboard/TestDashboardInstance.java +++ b/DashboardCore/src/test/java/com/acmerobotics/dashboard/TestDashboardInstance.java @@ -96,7 +96,7 @@ protected void onMessage(NanoWSD.WebSocketFrame message) { } send(new ReceiveRobotStatus( - new RobotStatus(core.enabled, true, opModeName, opModeStatus, "", "") + new RobotStatus(core.enabled, true, opModeName, opModeStatus, "", "", 12.0) )); break; } diff --git a/FtcDashboard/dash/src/components/Dashboard/Dashboard.tsx b/FtcDashboard/dash/src/components/Dashboard/Dashboard.tsx index 6d9d07016..5dad87c28 100644 --- a/FtcDashboard/dash/src/components/Dashboard/Dashboard.tsx +++ b/FtcDashboard/dash/src/components/Dashboard/Dashboard.tsx @@ -18,6 +18,9 @@ export default function Dashboard() { (state: RootState) => state.settings.layoutPreset, ); const enabled = useSelector((state: RootState) => state.status.enabled); + const batteryVoltage = useSelector( + (state: RootState) => state.status.batteryVoltage, + ); const dispatch = useDispatch(); const [isSettingsModalOpen, setIsSettingsModalOpen] = useState(false); @@ -58,11 +61,12 @@ export default function Dashboard() {

0 ? '120px' : '60px', textAlign: 'right', }} > {socket.pingTime}ms + {batteryVoltage > 0 ? ` / ${batteryVoltage.toFixed(2)}V` : ''}

)} {socket.isConnected ? ( diff --git a/FtcDashboard/dash/src/store/reducers/status.ts b/FtcDashboard/dash/src/store/reducers/status.ts index 3e30d8d28..031ce7c56 100644 --- a/FtcDashboard/dash/src/store/reducers/status.ts +++ b/FtcDashboard/dash/src/store/reducers/status.ts @@ -18,6 +18,7 @@ const initialState: StatusState = { errorMessage: '', opModeList: [], gamepadsSupported: true, + batteryVoltage: -1.0, }; const statusReducer = ( diff --git a/FtcDashboard/dash/src/store/types/status.ts b/FtcDashboard/dash/src/store/types/status.ts index 9b3024175..e6d07db29 100644 --- a/FtcDashboard/dash/src/store/types/status.ts +++ b/FtcDashboard/dash/src/store/types/status.ts @@ -13,6 +13,7 @@ export type RobotStatus = { activeOpModeStatus: Values; warningMessage: string; errorMessage: string; + batteryVoltage: number; }; export type StatusState = { @@ -22,6 +23,7 @@ export type StatusState = { activeOpModeStatus: Values; warningMessage: string; errorMessage: string; + batteryVoltage: number; opModeList: string[]; gamepadsSupported: boolean; }; diff --git a/FtcDashboard/src/main/java/com/acmerobotics/dashboard/FtcDashboard.java b/FtcDashboard/src/main/java/com/acmerobotics/dashboard/FtcDashboard.java index e6696becb..7cae70060 100644 --- a/FtcDashboard/src/main/java/com/acmerobotics/dashboard/FtcDashboard.java +++ b/FtcDashboard/src/main/java/com/acmerobotics/dashboard/FtcDashboard.java @@ -25,6 +25,7 @@ import com.acmerobotics.dashboard.message.redux.ReceiveRobotStatus; import com.acmerobotics.dashboard.telemetry.TelemetryPacket; import com.qualcomm.ftccommon.FtcEventLoop; +import com.qualcomm.hardware.lynx.LynxModule; import com.qualcomm.robotcore.eventloop.opmode.Disabled; import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode; import com.qualcomm.robotcore.eventloop.opmode.OpMode; @@ -59,6 +60,7 @@ import org.firstinspires.ftc.robotcore.external.Telemetry; import org.firstinspires.ftc.robotcore.external.function.Consumer; import org.firstinspires.ftc.robotcore.external.function.Continuation; +import org.firstinspires.ftc.robotcore.external.navigation.VoltageUnit; import org.firstinspires.ftc.robotcore.external.stream.CameraStreamSource; import org.firstinspires.ftc.robotcore.internal.opmode.OpModeMeta; import org.firstinspires.ftc.robotcore.internal.opmode.RegisteredOpModes; @@ -1185,14 +1187,23 @@ private void updateGamepads(ReceiveGamepadState.Gamepad gamepad1, private RobotStatus getRobotStatus() { if (opModeManager == null) { return new RobotStatus(core.enabled, false, "", RobotStatus.OpModeStatus.STOPPED, "", - ""); + "", -1.0); } else { return activeOpMode.with(o -> { + double batteryVoltage = -1.0; + if (o.opMode.hardwareMap != null) { + for (LynxModule m : o.opMode.hardwareMap.getAll(LynxModule.class)) { + batteryVoltage = + Math.max(batteryVoltage, m.getInputVoltage(VoltageUnit.VOLTS)); + } + } + return new RobotStatus( core.enabled, true, opModeManager.getActiveOpModeName(), // status is an enum so it's okay to return a copy here. o.status, - RobotLog.getGlobalWarningMessage().message, RobotLog.getGlobalErrorMsg() + RobotLog.getGlobalWarningMessage().message, RobotLog.getGlobalErrorMsg(), + batteryVoltage ); }); }