Files
PhotonVision/photon-client/src/stores/settings/GeneralSettingsStore.ts

191 lines
5.6 KiB
TypeScript
Raw Normal View History

import { defineStore } from "pinia";
import type {
ConfigurableNetworkSettings,
GeneralSettings,
LightingSettings,
MetricData,
NetworkSettings
} from "@/types/SettingTypes";
import { NetworkConnectionType } from "@/types/SettingTypes";
import { useStateStore } from "@/stores/StateStore";
import axios from "axios";
import type { WebsocketSettingsUpdate } from "@/types/WebsocketDataTypes";
import { ref } from "vue";
interface GeneralSettingsStore {
general: GeneralSettings;
network: NetworkSettings;
lighting: LightingSettings;
metrics: MetricData;
currentFieldLayout;
}
interface MetricsEntry {
time: number;
metrics: MetricData;
}
class MetricsHistory {
private MAX_METRIC_HISTORY = 60;
private UPDATE_INTERVAL_MS = 900;
private buffer: (MetricsEntry | undefined)[];
private size: number;
private index = 0;
private count = 0;
private lastUpdate = 0;
constructor(size = this.MAX_METRIC_HISTORY) {
this.size = size;
this.buffer = new Array<MetricsEntry | undefined>(size);
}
update(value: MetricsEntry): boolean {
const now = Date.now();
if (now - this.lastUpdate < this.UPDATE_INTERVAL_MS) return false;
this.lastUpdate = now;
this.buffer[this.index] = value;
this.index = (this.index + 1) % this.size;
this.count = Math.min(this.count + 1, this.size);
return true;
}
getHistory(): MetricsEntry[] {
const result: MetricsEntry[] = new Array(this.count);
for (let i = 0; i < this.count; i++) {
const idx = (this.index - this.count + i + this.size) % this.size;
result[i] = this.buffer[idx]!;
}
return result;
}
}
const metricsHistoryBuffer = new MetricsHistory();
export const metricsHistorySnapshot = ref<MetricsEntry[]>([]);
export const useSettingsStore = defineStore("settings", {
state: (): GeneralSettingsStore => ({
general: {
version: undefined,
imageVersion: undefined,
gpuAcceleration: undefined,
hardwareModel: undefined,
hardwarePlatform: undefined,
wpilibArch: undefined,
mrCalWorking: true,
availableModels: [],
supportedBackends: [],
conflictingHostname: false,
conflictingCameras: ""
},
network: {
ntServerAddress: "",
shouldManage: true,
canManage: true,
connectionType: NetworkConnectionType.DHCP,
staticIp: "",
hostname: "photonvision",
runNTServer: false,
shouldPublishProto: false,
networkInterfaceNames: [
{
connName: "Example Wired Connection",
devName: "eth0"
}
],
General UI Refinements (#1678) Does the following: - Adjusts the shade of red buttons and banners to increase readability and reduce eye strain ![image](https://github.com/user-attachments/assets/7f741a9e-dc1e-4394-b87d-580e189245b1) ![image](https://github.com/user-attachments/assets/b23202f1-4cf6-46c1-aca5-2455a09259cd) - Cleans up factory reset and camera deletion modals ![image](https://github.com/user-attachments/assets/e6564732-d578-43da-bc83-729ec6fdbc5e) ![image](https://github.com/user-attachments/assets/9c5a1cba-f4fd-47ea-811c-abbabe5fa3a4) - Removes matchCamerasOnlyByPath as it is no longer used and throws errors in the console ![image](https://github.com/user-attachments/assets/77043993-26a2-4de4-8e98-702e7f285dc6) - Limits the criteria to flag a camera mismatch in Camera Matching to only what is necessary based on camera type and highlights differences in table properties (testing on this is appreciated) ![image](https://github.com/user-attachments/assets/cfbd96c1-09dd-414a-8177-693fc054b26f) - Only displays both saved vs. current info in camera matching if there is a difference between the two ![image](https://github.com/user-attachments/assets/6223ffc8-4cff-464f-8b54-720c3222a5d5) - Some general code cleanup (reduced unnecessary padding/margin/row-col statements, style="display:flex;" -> class="d-flex", etc. - Moves Compact Mode button to the bottom away from all the menu items (cleaner imo, open to thoughts) - Establishes a general spacing format for cards and pages and applies this to existing cards and pages to create a consistent look and feel to the UI (e.g. keeping things in line and less erratic spacing/placement of UI elements) ![image](https://github.com/user-attachments/assets/1ab0ca4b-303e-436d-97b3-da72d46c4fcb) ![image](https://github.com/user-attachments/assets/82ba9e53-f854-4309-bc00-7b5d0bad58b7) ![image](https://github.com/user-attachments/assets/18aa6ca4-e6fa-4125-8a0a-e6a007a0337d) ![image](https://github.com/user-attachments/assets/77043993-26a2-4de4-8e98-702e7f285dc6) - Delete protection for camera matching modules - Anti-backend-spam for activate/deactivate/delete modules to hopefully prevent any odd behavior from button spamming - Enforces a common camera stream size on camera matching view (NEEDS MORE TESTING) ![image](https://github.com/user-attachments/assets/9032783d-1edf-4c6e-ba7b-00e5f20280df) https://private-user-images.githubusercontent.com/29715865/400783758-dc99c151-b8a7-4367-a173-74c2fc5b2666.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MzYyNTc3NzEsIm5iZiI6MTczNjI1NzQ3MSwicGF0aCI6Ii8yOTcxNTg2NS80MDA3ODM3NTgtZGM5OWMxNTEtYjhhNy00MzY3LWExNzMtNzRjMmZjNWIyNjY2Lm1wND9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTAxMDclMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwMTA3VDEzNDQzMVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWMwOWM1MDc2ZTVlOWZhM2MxYjAwZjAyZTc2MTYyZTk1ZTVmOGFhZmVkMzlmODRlZTk1ODVlOTk2ZGQzZmM0Y2EmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.ovtRnObwbkEfljr9d5fqaory0nH91LWJSSkmrUUe_4Y
2025-01-07 08:45:39 -05:00
networkingDisabled: false
},
lighting: {
supported: true,
brightness: 0
},
metrics: {
cpuTemp: undefined,
cpuUtil: undefined,
cpuThr: undefined,
ramMem: undefined,
ramUtil: undefined,
gpuMem: undefined,
gpuMemUtil: undefined,
diskUtilPct: undefined,
diskUsableSpace: undefined,
npuUsage: undefined,
ipAddress: undefined,
uptime: undefined,
sentBitRate: undefined,
recvBitRate: undefined
2023-10-17 10:20:00 -04:00
},
currentFieldLayout: {
field: {
length: 16.4592,
width: 8.2296
},
tags: []
}
}),
getters: {
gpuAccelerationEnabled(): boolean {
return this.general.gpuAcceleration !== undefined;
},
networkInterfaceNames(): string[] {
return this.network.networkInterfaceNames.map((i) => i.devName);
}
},
actions: {
updateMetricsFromWebsocket(data: Required<MetricData>) {
this.metrics = {
cpuTemp: data.cpuTemp || undefined,
cpuUtil: data.cpuUtil || undefined,
cpuThr: data.cpuThr || undefined,
ramMem: data.ramMem || undefined,
ramUtil: data.ramUtil || undefined,
gpuMem: data.gpuMem || undefined,
gpuMemUtil: data.gpuMemUtil || undefined,
diskUtilPct: data.diskUtilPct || undefined,
diskUsableSpace: data.diskUsableSpace || undefined,
npuUsage: data.npuUsage || undefined,
ipAddress: data.ipAddress || undefined,
uptime: data.uptime || undefined,
sentBitRate: data.sentBitRate || undefined,
recvBitRate: data.recvBitRate || undefined
};
if (metricsHistoryBuffer.update({ time: Date.now(), metrics: this.metrics })) {
metricsHistorySnapshot.value = metricsHistoryBuffer.getHistory();
}
},
updateGeneralSettingsFromWebsocket(data: WebsocketSettingsUpdate) {
this.general = {
version: data.general.version || undefined,
imageVersion: data.general.imageVersion || undefined,
hardwareModel: data.general.hardwareModel || undefined,
hardwarePlatform: data.general.hardwarePlatform || undefined,
wpilibArch: data.general.wpilibArch || undefined,
gpuAcceleration: data.general.gpuAcceleration || undefined,
mrCalWorking: data.general.mrCalWorking,
availableModels: data.general.availableModels || undefined,
supportedBackends: data.general.supportedBackends || [],
conflictingHostname: data.general.conflictingHostname || false,
conflictingCameras: data.general.conflictingCameras || ""
};
this.lighting = data.lighting;
this.network = data.networkSettings;
2023-10-17 10:20:00 -04:00
this.currentFieldLayout = data.atfl;
},
updateGeneralSettings(payload: Required<ConfigurableNetworkSettings>) {
return axios.post("/settings/general", payload);
},
/**
* Modify the brightness of the LEDs.
*
* @param brightness brightness to set [0, 100]
*/
changeLEDBrightness(brightness: number) {
const payload = {
enabledLEDPercentage: brightness
};
useStateStore().websocket?.send(payload, true);
}
}
});