| 
					
				 | 
			
			
				@@ -1,36 +1,24 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { h } from 'preact'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { h, Fragment } from 'preact'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import ActivityIndicator from '../components/ActivityIndicator'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import Button from '../components/Button'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import Heading from '../components/Heading'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import Link from '../components/Link'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { useMqtt } from '../api/mqtt'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { useConfig, useStats } from '../api'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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({}); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 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 detectorDataKeys = Object.keys(detectors ? detectors[detectorNames[0]] : emptyObject); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -44,61 +32,69 @@ export default function Debug() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     copy(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   }, [config]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return stats === null ? ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    <ActivityIndicator /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  ) : ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <div className="space-y-4"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <Heading> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         Debug <span className="text-sm">{service.version}</span> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       </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"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <Heading size="sm">Config</Heading> 
			 |