From d073b3a4180b27c610bdfbdee2dcc5cf47535ece Mon Sep 17 00:00:00 2001 From: Ruthie Date: Sun, 15 Mar 2026 16:31:07 +0000 Subject: [PATCH 1/7] Add export settings functionality with option to exclude calibration images --- .../src/components/settings/DeviceCard.vue | 47 +++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/photon-client/src/components/settings/DeviceCard.vue b/photon-client/src/components/settings/DeviceCard.vue index 69482bd7fe..61f0728eb2 100644 --- a/photon-client/src/components/settings/DeviceCard.vue +++ b/photon-client/src/components/settings/DeviceCard.vue @@ -4,6 +4,7 @@ import { inject, computed, ref, watch } from "vue"; import { useStateStore } from "@/stores/StateStore"; import { useSettingsStore } from "@/stores/settings/GeneralSettingsStore"; import PvSelect from "@/components/common/pv-select.vue"; +import PvSwitch from "@/components/common/pv-switch.vue"; import PvDeleteModal from "@/components/common/pv-delete-modal.vue"; import MetricsChart from "./MetricsChart.vue"; import { useTheme } from "vuetify"; @@ -128,9 +129,15 @@ const openExportLogsPrompt = () => { }; const exportSettings = ref(); +const showExportDialog = ref(false); +const excludeImages = ref(false); const openExportSettingsPrompt = () => { exportSettings.value.click(); }; +const doExportSettings = () => { + showExportDialog.value = false; + exportSettings.value.click(); +}; enum ImportType { AllSettings, @@ -356,7 +363,7 @@ watch(metricsHistorySnapshot, () => { mdi-export Export Settings @@ -540,6 +547,40 @@ watch(metricsHistorySnapshot, () => { + + + + Export Settings + + Download a ZIP archive of all PhotonVision settings from this device +
+ + + mdi-export + Export Settings + +
+
+
+
+ Offline Update @@ -570,7 +611,7 @@ watch(metricsHistorySnapshot, () => { @@ -591,4 +632,4 @@ watch(metricsHistorySnapshot, () => { display: none; } } - + \ No newline at end of file From b2d201c02025cd0325c1d1659c0bb8df2fbc5ee2 Mon Sep 17 00:00:00 2001 From: Ruthie Date: Sun, 15 Mar 2026 16:32:35 +0000 Subject: [PATCH 2/7] Add option to exclude calibration images when exporting settings as zip --- .../common/configuration/ConfigManager.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java b/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java index d8fe576228..3c9436ee52 100644 --- a/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java +++ b/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java @@ -214,9 +214,28 @@ public void saveModule(CameraConfiguration config, String uniqueName) { } public File getSettingsFolderAsZip() { + return getSettingsFolderAsZip(false); + } + + public File getSettingsFolderAsZip(boolean excludeImages) { File out = Path.of(System.getProperty("java.io.tmpdir"), "photonvision-settings.zip").toFile(); try { - ZipUtil.pack(configDirectoryFile, out); + if (excludeImages) { + ZipUtil.pack( + configDirectoryFile, + out, + name -> { + // Exclude calibration images and saved snapshots + if (name.startsWith("calibImgs/") + || name.startsWith("calibration/") + || name.startsWith("imgSaves/")) { + return null; + } + return name; + }); + } else { + ZipUtil.pack(configDirectoryFile, out); + } } catch (Exception e) { e.printStackTrace(); } @@ -392,4 +411,4 @@ public void onJvmExit() { saveToDisk(); } } -} +} \ No newline at end of file From 220304a4990f3f91b55f12e9a1685fcd297901b4 Mon Sep 17 00:00:00 2001 From: Ruthie Date: Sun, 15 Mar 2026 16:33:20 +0000 Subject: [PATCH 3/7] Add option to exclude images when exporting settings to ZIP --- .../main/java/org/photonvision/server/RequestHandler.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java index c6ed9b8d24..53bf57b597 100644 --- a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java +++ b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java @@ -134,10 +134,11 @@ public static void onSettingsImportRequest(Context ctx) { } public static void onSettingsExportRequest(Context ctx) { - logger.info("Exporting Settings to ZIP Archive"); + boolean excludeImages = Boolean.parseBoolean(ctx.queryParam("excludeImages")); + logger.info("Exporting Settings to ZIP Archive (excludeImages=" + excludeImages + ")"); try { - var zip = ConfigManager.getInstance().getSettingsFolderAsZip(); + var zip = ConfigManager.getInstance().getSettingsFolderAsZip(excludeImages); var stream = new FileInputStream(zip); logger.info("Uploading settings with size " + stream.available()); @@ -1411,4 +1412,4 @@ public static void onUnassignCameraRequest(Context ctx) { return; } } -} +} \ No newline at end of file From 107a65b4d67c98521255058e8a238bcaf74d0349 Mon Sep 17 00:00:00 2001 From: Ruthie Date: Sun, 15 Mar 2026 16:35:08 +0000 Subject: [PATCH 4/7] Add package-lock.json to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6a3ddc0b6f..a709d075e1 100644 --- a/.gitignore +++ b/.gitignore @@ -156,3 +156,4 @@ photon-client/playwright-report/ photon-client/blob-report/ photon-client/playwright/.cache/ photon-client/playwright/.auth/ +photon-client/package-lock.json From e72e036cdf696d9bb89cbb1fe81914574ff74274 Mon Sep 17 00:00:00 2001 From: Ruthie Date: Sun, 15 Mar 2026 16:44:30 +0000 Subject: [PATCH 5/7] Fix missing newline at end of file in ConfigManager and RequestHandler --- .../org/photonvision/common/configuration/ConfigManager.java | 2 +- .../src/main/java/org/photonvision/server/RequestHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java b/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java index 3c9436ee52..48de1531b6 100644 --- a/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java +++ b/photon-core/src/main/java/org/photonvision/common/configuration/ConfigManager.java @@ -411,4 +411,4 @@ public void onJvmExit() { saveToDisk(); } } -} \ No newline at end of file +} diff --git a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java index 53bf57b597..1a0f7cef30 100644 --- a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java +++ b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java @@ -1412,4 +1412,4 @@ public static void onUnassignCameraRequest(Context ctx) { return; } } -} \ No newline at end of file +} From 1b2f1ea3880a9b2c96b2d67bb66394c55497f25c Mon Sep 17 00:00:00 2001 From: Ruthie Date: Sun, 15 Mar 2026 16:49:59 +0000 Subject: [PATCH 6/7] Fix missing newline at end of file in DeviceCard.vue --- photon-client/src/components/settings/DeviceCard.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/photon-client/src/components/settings/DeviceCard.vue b/photon-client/src/components/settings/DeviceCard.vue index 61f0728eb2..5f935414bb 100644 --- a/photon-client/src/components/settings/DeviceCard.vue +++ b/photon-client/src/components/settings/DeviceCard.vue @@ -632,4 +632,4 @@ watch(metricsHistorySnapshot, () => { display: none; } } - \ No newline at end of file + From 1fe36e4652247d6a0606717c1ff7d6825072dc32 Mon Sep 17 00:00:00 2001 From: Ruthie Date: Mon, 16 Mar 2026 11:56:34 -0500 Subject: [PATCH 7/7] Implement thermal throttling alert and fix typos Added thermal throttling alert and updated related comments. --- .../hardware/metrics/SystemMonitor.java | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/photon-core/src/main/java/org/photonvision/common/hardware/metrics/SystemMonitor.java b/photon-core/src/main/java/org/photonvision/common/hardware/metrics/SystemMonitor.java index a9401649be..abadc0fc8e 100644 --- a/photon-core/src/main/java/org/photonvision/common/hardware/metrics/SystemMonitor.java +++ b/photon-core/src/main/java/org/photonvision/common/hardware/metrics/SystemMonitor.java @@ -20,6 +20,9 @@ import edu.wpi.first.cscore.CameraServerJNI; import edu.wpi.first.networktables.NetworkTable; import edu.wpi.first.networktables.ProtobufPublisher; +import edu.wpi.first.wpilibj.Alert; +import edu.wpi.first.wpilibj.Alert.AlertType; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import java.io.IOException; import java.nio.file.FileStore; import java.nio.file.Files; @@ -62,6 +65,9 @@ private record NetworkTraffic(double sentBitRate, double recvBitRate) {} .getProtobufTopic(CameraServerJNI.getHostname(), DeviceMetrics.proto) .publish(); + private final Alert thermalThrottlingAlert = + new Alert("PhotonAlerts", "Thermal throttling detected!", AlertType.kWarning); + private SystemInfo si; private CentralProcessor cpu; private OperatingSystem os; @@ -140,11 +146,11 @@ protected SystemMonitor() { } /** - * Returns a comma-separated list of addtional thermal zone types that should be checked to get + * Returns a comma-separated list of additional thermal zone types that should be checked to get * the CPU temperature on Unix systems. The temperature will be reported for the first temperature - * zone with a type that mateches an item of this list. If the CPU temperature isn't being - * reported correctly for a coprocessor, override this method to return a string with type - * associated with the thermal zone for that comprocessor. + * zone with a type that matches an item of this list. If the CPU temperature isn't being reported + * correctly for a coprocessor, override this method to return a string with type associated with + * the thermal zone for that coprocessor. * * @return String containing a comma-separated list of thermal zone types for reading CPU * temperature. @@ -159,7 +165,7 @@ protected String getThermalZoneTypes() { /** * Starts the periodic system monitor that publishes performance metrics. The metrics are - * published every millisUpdateInerval seconds after a millisStartDelay startup delay. Calling + * published every millisUpdateInterval seconds after a millisStartDelay startup delay. Calling * this method when the monitor is running will stop it and restart it with the new delay and * update interval. * @@ -210,6 +216,9 @@ private void publishMetrics() { metricPublisher.set(metrics); + thermalThrottlingAlert.set(this.isThermallyThrottling()); + SmartDashboard.updateValues(); + if (writeMetricsToLog) { logMetrics(metrics); } @@ -233,7 +242,7 @@ private void logMetrics(DeviceMetrics metrics) { String.format("CPU Throttle: %s, ", metrics.cpuThr().isBlank() ? "N/A" : metrics.cpuThr())); sb.append( String.format( - "Data sent: %.0f Kbps, Data recieved: %.0f Kbps", + "Data sent: %.0f Kbps, Data received: %.0f Kbps", metrics.sentBitRate() / 1000, metrics.recvBitRate() / 1000)); logger.debug(sb.toString()); } @@ -446,6 +455,16 @@ public String getCpuThrottleReason() { return ""; } + /** + * Returns true if the device is currently experiencing thermal throttling. Platforms that support + * thermal throttling detection will override this method. + * + * @return true if thermally throttling, false otherwise. + */ + public boolean isThermallyThrottling() { + return false; + } + /** * Returns the total GPU memory in MiB. * @@ -475,7 +494,7 @@ public String getIpAddress() { } /** - * Returns a NetworkTraffic instance containing the average sent and recieved network traffic + * Returns a NetworkTraffic instance containing the average sent and received network traffic * since the last time this was called. * * @return NetworkTraffic instance with data in bits/second. The traffic values will be -1 if the @@ -537,7 +556,7 @@ private void testSM() { () -> { var nt = getNetworkTraffic(); return String.format( - "Data sent: %.0f Kbps, Data recieved: %.0f Kbps", + "Data sent: %.0f Kbps, Data received: %.0f Kbps", nt.sentBitRate() / 1000, nt.recvBitRate() / 1000); });