import useSWR from "swr"; import { FrigateStats } from "@/types/stats"; import { useState } from "react"; import TimeAgo from "@/components/dynamic/TimeAgo"; import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; import { isDesktop, isMobile } from "react-device-detect"; import GeneralMetrics from "@/views/system/GeneralMetrics"; import StorageMetrics from "@/views/system/StorageMetrics"; import { LuActivity, LuHardDrive } from "react-icons/lu"; import { FaVideo } from "react-icons/fa"; import Logo from "@/components/Logo"; import useOptimisticState from "@/hooks/use-optimistic-state"; const metrics = ["general", "storage", "cameras"] as const; type SystemMetric = (typeof metrics)[number]; function System() { // stats page const [page, setPage] = useState("general"); const [pageToggle, setPageToggle] = useOptimisticState(page, setPage, 100); const [lastUpdated, setLastUpdated] = useState(Date.now() / 1000); // stats collection const { data: statsSnapshot } = useSWR("stats", { revalidateOnFocus: false, }); return (
{isMobile && ( )} { if (value) { setPageToggle(value); } }} // don't allow the severity to be unselected > {Object.values(metrics).map((item) => ( {item == "general" && } {item == "storage" && } {item == "cameras" && } {isDesktop &&
{item}
}
))}
{lastUpdated && (
Last refreshed:
)}
System
{statsSnapshot && (
{statsSnapshot.service.version}
)}
{page == "general" && ( )} {page == "storage" && }
); } export default System; /** * const cameraCpuSeries = useMemo(() => { if (!statsHistory || statsHistory.length == 0) { return {}; } const series: { [cam: string]: { [key: string]: { name: string; data: { x: object; y: string }[] }; }; } = {}; statsHistory.forEach((stats, statsIdx) => { if (!stats) { return; } const statTime = new Date(stats.service.last_updated * 1000); Object.entries(stats.cameras).forEach(([key, camStats]) => { if (!config?.cameras[key].enabled) { return; } if (!(key in series)) { const camName = key.replaceAll("_", " "); series[key] = {}; series[key]["ffmpeg"] = { name: `${camName} ffmpeg`, data: [] }; series[key]["capture"] = { name: `${camName} capture`, data: [] }; series[key]["detect"] = { name: `${camName} detect`, data: [] }; } series[key]["ffmpeg"].data.push({ x: statsIdx, y: stats.cpu_usages[camStats.ffmpeg_pid.toString()]?.cpu ?? 0.0, }); series[key]["capture"].data.push({ x: statsIdx, y: stats.cpu_usages[camStats.capture_pid?.toString()]?.cpu ?? 0, }); series[key]["detect"].data.push({ x: statsIdx, y: stats.cpu_usages[camStats.pid.toString()].cpu, }); }); }); return series; }, [statsHistory]); const cameraFpsSeries = useMemo(() => { if (!statsHistory) { return {}; } const series: { [cam: string]: { [key: string]: { name: string; data: { x: object; y: number }[] }; }; } = {}; statsHistory.forEach((stats, statsIdx) => { if (!stats) { return; } const statTime = new Date(stats.service.last_updated * 1000); Object.entries(stats.cameras).forEach(([key, camStats]) => { if (!(key in series)) { const camName = key.replaceAll("_", " "); series[key] = {}; series[key]["det"] = { name: `${camName} detections`, data: [] }; series[key]["skip"] = { name: `${camName} skipped detections`, data: [], }; } series[key]["det"].data.push({ x: statsIdx, y: camStats.detection_fps, }); series[key]["skip"].data.push({ x: statsIdx, y: camStats.skipped_fps, }); }); }); return series; }, [statsHistory]); * *
Cameras
{config && Object.values(config.cameras).map((camera) => { if (camera.enabled) { return (
); } return null; })}
*/