mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-19 00:41:41 +00:00
## Description WPILib switched from FasterXML Jackson to Avaje Jsonb for speed reasons in https://github.com/wpilibsuite/allwpilib/pull/8721. This does the same for PhotonVision. Some temporary Jackson adapters are present to allow compatibility with alpha-4 ahead of updating Photon's WPILib version. A few old backwards compatibility migrations were also dropped if they were difficult to port to Avaje Jsonb or otherwise complicated the code. ## Meta Merge checklist: - [x] Pull Request title is [short, imperative summary](https://cbea.ms/git-commit/) of proposed changes - [x] The description documents the _what_ and _why_, including events that led to this PR - [ ] If this PR changes behavior or adds a feature, user documentation is updated - [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly - [ ] If this PR touches configuration, this is backwards compatible with all settings going back to the previous seasons's last release (seasons end after champs ends) - [ ] If this PR touches pipeline settings or anything related to data exchange, the frontend typing is updated - [ ] If this PR addresses a bug, a regression test for it is added - [ ] If this PR adds a dependency, the license has been checked for compatibility and steps taken to follow it --------- Co-authored-by: samfreund <samf.236@proton.me> Co-authored-by: Matt Morley <matthew.morley.ca@gmail.com>
112 lines
4.1 KiB
TypeScript
112 lines
4.1 KiB
TypeScript
import { useStateStore } from "@/stores/StateStore";
|
|
import type { Resolution } from "@/types/SettingTypes";
|
|
import axios, { type AxiosRequestConfig } from "axios";
|
|
|
|
export const resolutionsAreEqual = (a: Resolution, b: Resolution) => {
|
|
return a.height === b.height && a.width === b.width;
|
|
};
|
|
|
|
/**
|
|
* Checks the status of the backend by polling the "/status" endpoint.
|
|
*
|
|
* This function will repeatedly attempt to send a GET request to the backend
|
|
* until a successful response is received or the specified timeout is reached.
|
|
*
|
|
* @param timeout - The maximum time in milliseconds to wait for a successful response.
|
|
* @param ip - Optional IP address of the backend server. If not provided, the default endpoint is used. This is meant for the case where the backend is running on a different IP than the frontend.
|
|
* @returns A promise that resolves to a boolean indicating whether the backend is responsive (true) or not (false).
|
|
*/
|
|
export const statusCheck = async (timeout: number, ip?: string): Promise<boolean> => {
|
|
// Poll the backend until it's responsive or we hit the timeout
|
|
let pollLimit = Math.floor(timeout / 100);
|
|
while (pollLimit > 0) {
|
|
try {
|
|
pollLimit--;
|
|
await axios.get(ip ? `http://${ip}/api/status` : "/status");
|
|
return true;
|
|
} catch {
|
|
// Backend not ready yet, wait and retry
|
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* Forces a page reload after a brief delay and a status check.
|
|
*/
|
|
export const forceReloadPage = async () => {
|
|
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
message: "Reloading the page to apply changes...",
|
|
color: "success"
|
|
});
|
|
|
|
await statusCheck(20000);
|
|
|
|
window.location.reload();
|
|
};
|
|
|
|
export const getResolutionString = (resolution: Resolution): string => `${resolution.width}x${resolution.height}`;
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
export const parseJsonFile = async <T extends Record<string, any>>(file: File): Promise<T> => {
|
|
return new Promise((resolve, reject) => {
|
|
const fileReader = new FileReader();
|
|
fileReader.onload = (event) => {
|
|
const target: FileReader | null = event.target;
|
|
if (target === null) reject(new Error("FileReader event target is null"));
|
|
else resolve(JSON.parse(target.result as string) as T);
|
|
};
|
|
fileReader.onerror = () => reject(new Error("Error reading file"));
|
|
fileReader.readAsText(file);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* A helper function to make POST requests using axios with standardized success and error handling.
|
|
*
|
|
* @param url The endpoint URL to which the POST request is sent
|
|
* @param description A brief description of the request for users, e.g., "import object detection models".
|
|
* @param data Payload to be sent in the POST request
|
|
* @param config Optional axios request configuration
|
|
* @returns A promise that resolves to true if the POST request is successful, or false if an error occurs.
|
|
*/
|
|
export const axiosPost = async (
|
|
url: string,
|
|
description: string,
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
data?: any,
|
|
config?: AxiosRequestConfig
|
|
): Promise<boolean> => {
|
|
try {
|
|
await axios.post(url, data, config);
|
|
useStateStore().showSnackbarMessage({
|
|
message: "Successfully dispatched the request to " + description + ". Waiting for backend to respond",
|
|
color: "success"
|
|
});
|
|
return true;
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
} catch (error: any) {
|
|
if (error.response) {
|
|
useStateStore().showSnackbarMessage({
|
|
message: "The backend is unable to fulfill the request to " + description + ".",
|
|
color: "error"
|
|
});
|
|
} else if (error.request) {
|
|
useStateStore().showSnackbarMessage({
|
|
message: "Error while trying to process the request to " + description + "! The backend didn't respond.",
|
|
color: "error"
|
|
});
|
|
} else {
|
|
useStateStore().showSnackbarMessage({
|
|
message: "An error occurred while trying to process the request to " + description + ".",
|
|
color: "error"
|
|
});
|
|
}
|
|
return false;
|
|
}
|
|
};
|