|
@@ -1,36 +1,24 @@
|
|
-import { h } from 'preact';
|
|
|
|
|
|
+import { h, Fragment } from 'preact';
|
|
import ActivityIndicator from '../components/ActivityIndicator';
|
|
import ActivityIndicator from '../components/ActivityIndicator';
|
|
import Button from '../components/Button';
|
|
import Button from '../components/Button';
|
|
import Heading from '../components/Heading';
|
|
import Heading from '../components/Heading';
|
|
import Link from '../components/Link';
|
|
import Link from '../components/Link';
|
|
|
|
+import { useMqtt } from '../api/mqtt';
|
|
import { useConfig, useStats } from '../api';
|
|
import { useConfig, useStats } from '../api';
|
|
import { Table, Tbody, Thead, Tr, Th, Td } from '../components/Table';
|
|
import { Table, Tbody, Thead, Tr, Th, Td } from '../components/Table';
|
|
-import { useCallback, useEffect, useState } from 'preact/hooks';
|
|
|
|
|
|
+import { useCallback } from 'preact/hooks';
|
|
|
|
|
|
const emptyObject = Object.freeze({});
|
|
const emptyObject = Object.freeze({});
|
|
|
|
|
|
export default function Debug() {
|
|
export default function Debug() {
|
|
- const config = useConfig();
|
|
|
|
|
|
+ const { data: config } = useConfig();
|
|
|
|
|
|
- const [timeoutId, setTimeoutId] = useState(null);
|
|
|
|
- const { data: stats } = useStats(null, timeoutId);
|
|
|
|
|
|
+ const {
|
|
|
|
+ value: { stats },
|
|
|
|
+ } = useMqtt('stats');
|
|
|
|
+ const { data: initialStats } = useStats();
|
|
|
|
|
|
- const forceUpdate = useCallback(() => {
|
|
|
|
- const timeoutId = setTimeout(forceUpdate, 1000);
|
|
|
|
- setTimeoutId(timeoutId);
|
|
|
|
- }, []);
|
|
|
|
-
|
|
|
|
- useEffect(() => {
|
|
|
|
- forceUpdate();
|
|
|
|
- }, [forceUpdate]);
|
|
|
|
-
|
|
|
|
- useEffect(() => {
|
|
|
|
- return () => {
|
|
|
|
- clearTimeout(timeoutId);
|
|
|
|
- };
|
|
|
|
- }, [timeoutId]);
|
|
|
|
-
|
|
|
|
- const { detectors, service, detection_fps, ...cameras } = stats || emptyObject;
|
|
|
|
|
|
+ const { detectors, service = {}, detection_fps, ...cameras } = stats || initialStats || emptyObject;
|
|
|
|
|
|
const detectorNames = Object.keys(detectors || emptyObject);
|
|
const detectorNames = Object.keys(detectors || emptyObject);
|
|
const detectorDataKeys = Object.keys(detectors ? detectors[detectorNames[0]] : emptyObject);
|
|
const detectorDataKeys = Object.keys(detectors ? detectors[detectorNames[0]] : emptyObject);
|
|
@@ -44,61 +32,69 @@ export default function Debug() {
|
|
copy();
|
|
copy();
|
|
}, [config]);
|
|
}, [config]);
|
|
|
|
|
|
- return stats === null ? (
|
|
|
|
- <ActivityIndicator />
|
|
|
|
- ) : (
|
|
|
|
|
|
+ return (
|
|
<div className="space-y-4">
|
|
<div className="space-y-4">
|
|
<Heading>
|
|
<Heading>
|
|
Debug <span className="text-sm">{service.version}</span>
|
|
Debug <span className="text-sm">{service.version}</span>
|
|
</Heading>
|
|
</Heading>
|
|
|
|
|
|
- <div data-testid="detectors" className="min-w-0 overflow-auto">
|
|
|
|
- <Table className="w-full">
|
|
|
|
- <Thead>
|
|
|
|
- <Tr>
|
|
|
|
- <Th>detector</Th>
|
|
|
|
- {detectorDataKeys.map((name) => (
|
|
|
|
- <Th>{name.replace('_', ' ')}</Th>
|
|
|
|
- ))}
|
|
|
|
- </Tr>
|
|
|
|
- </Thead>
|
|
|
|
- <Tbody>
|
|
|
|
- {detectorNames.map((detector, i) => (
|
|
|
|
- <Tr index={i}>
|
|
|
|
- <Td>{detector}</Td>
|
|
|
|
- {detectorDataKeys.map((name) => (
|
|
|
|
- <Td key={`${name}-${detector}`}>{detectors[detector][name]}</Td>
|
|
|
|
|
|
+ {!detectors ? (
|
|
|
|
+ <div>
|
|
|
|
+ <ActivityIndicator />
|
|
|
|
+ </div>
|
|
|
|
+ ) : (
|
|
|
|
+ <Fragment>
|
|
|
|
+ <div data-testid="detectors" className="min-w-0 overflow-auto">
|
|
|
|
+ <Table className="w-full">
|
|
|
|
+ <Thead>
|
|
|
|
+ <Tr>
|
|
|
|
+ <Th>detector</Th>
|
|
|
|
+ {detectorDataKeys.map((name) => (
|
|
|
|
+ <Th>{name.replace('_', ' ')}</Th>
|
|
|
|
+ ))}
|
|
|
|
+ </Tr>
|
|
|
|
+ </Thead>
|
|
|
|
+ <Tbody>
|
|
|
|
+ {detectorNames.map((detector, i) => (
|
|
|
|
+ <Tr index={i}>
|
|
|
|
+ <Td>{detector}</Td>
|
|
|
|
+ {detectorDataKeys.map((name) => (
|
|
|
|
+ <Td key={`${name}-${detector}`}>{detectors[detector][name]}</Td>
|
|
|
|
+ ))}
|
|
|
|
+ </Tr>
|
|
))}
|
|
))}
|
|
- </Tr>
|
|
|
|
- ))}
|
|
|
|
- </Tbody>
|
|
|
|
- </Table>
|
|
|
|
- </div>
|
|
|
|
|
|
+ </Tbody>
|
|
|
|
+ </Table>
|
|
|
|
+ </div>
|
|
|
|
|
|
- <div data-testid="cameras" className="min-w-0 overflow-auto">
|
|
|
|
- <Table className="w-full">
|
|
|
|
- <Thead>
|
|
|
|
- <Tr>
|
|
|
|
- <Th>camera</Th>
|
|
|
|
- {cameraDataKeys.map((name) => (
|
|
|
|
- <Th>{name.replace('_', ' ')}</Th>
|
|
|
|
- ))}
|
|
|
|
- </Tr>
|
|
|
|
- </Thead>
|
|
|
|
- <Tbody>
|
|
|
|
- {cameraNames.map((camera, i) => (
|
|
|
|
- <Tr index={i}>
|
|
|
|
- <Td>
|
|
|
|
- <Link href={`/cameras/${camera}`}>{camera}</Link>
|
|
|
|
- </Td>
|
|
|
|
- {cameraDataKeys.map((name) => (
|
|
|
|
- <Td key={`${name}-${camera}`}>{cameras[camera][name]}</Td>
|
|
|
|
|
|
+ <div data-testid="cameras" className="min-w-0 overflow-auto">
|
|
|
|
+ <Table className="w-full">
|
|
|
|
+ <Thead>
|
|
|
|
+ <Tr>
|
|
|
|
+ <Th>camera</Th>
|
|
|
|
+ {cameraDataKeys.map((name) => (
|
|
|
|
+ <Th>{name.replace('_', ' ')}</Th>
|
|
|
|
+ ))}
|
|
|
|
+ </Tr>
|
|
|
|
+ </Thead>
|
|
|
|
+ <Tbody>
|
|
|
|
+ {cameraNames.map((camera, i) => (
|
|
|
|
+ <Tr index={i}>
|
|
|
|
+ <Td>
|
|
|
|
+ <Link href={`/cameras/${camera}`}>{camera}</Link>
|
|
|
|
+ </Td>
|
|
|
|
+ {cameraDataKeys.map((name) => (
|
|
|
|
+ <Td key={`${name}-${camera}`}>{cameras[camera][name]}</Td>
|
|
|
|
+ ))}
|
|
|
|
+ </Tr>
|
|
))}
|
|
))}
|
|
- </Tr>
|
|
|
|
- ))}
|
|
|
|
- </Tbody>
|
|
|
|
- </Table>
|
|
|
|
- </div>
|
|
|
|
|
|
+ </Tbody>
|
|
|
|
+ </Table>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <p>Debug stats update automatically every {config.mqtt.stats_interval} seconds.</p>
|
|
|
|
+ </Fragment>
|
|
|
|
+ )}
|
|
|
|
|
|
<div className="relative">
|
|
<div className="relative">
|
|
<Heading size="sm">Config</Heading>
|
|
<Heading size="sm">Config</Heading>
|