From 2be8b91c1572b707b99e4c0eda4eefbfb811f1e9 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 1 Mar 2024 12:58:03 -0700 Subject: [PATCH] Get ptz working --- web/src/pages/Live.tsx | 13 +- web/src/types/ptz.ts | 7 ++ web/src/views/live/LiveCameraView.tsx | 166 +++++++++++++++++++++++++- 3 files changed, 173 insertions(+), 13 deletions(-) create mode 100644 web/src/types/ptz.ts diff --git a/web/src/pages/Live.tsx b/web/src/pages/Live.tsx index ba0811ecc..25c6fdb1b 100644 --- a/web/src/pages/Live.tsx +++ b/web/src/pages/Live.tsx @@ -1,19 +1,8 @@ -import { useFrigateReviews } from "@/api/ws"; -import Logo from "@/components/Logo"; -import { AnimatedEventThumbnail } from "@/components/image/AnimatedEventThumbnail"; -import LivePlayer from "@/components/player/LivePlayer"; -import { Button } from "@/components/ui/button"; -import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area"; -import { TooltipProvider } from "@/components/ui/tooltip"; import useOverlayState from "@/hooks/use-overlay-state"; -import { usePersistence } from "@/hooks/use-persistence"; import { FrigateConfig } from "@/types/frigateConfig"; -import { ReviewSegment } from "@/types/review"; import LiveCameraView from "@/views/live/LiveCameraView"; import LiveDashboardView from "@/views/live/LiveDashboardView"; -import { useCallback, useEffect, useMemo, useState } from "react"; -import { isDesktop, isMobile, isSafari } from "react-device-detect"; -import { CiGrid2H, CiGrid31 } from "react-icons/ci"; +import { useMemo } from "react"; import useSWR from "swr"; function Live() { diff --git a/web/src/types/ptz.ts b/web/src/types/ptz.ts new file mode 100644 index 000000000..1a626972e --- /dev/null +++ b/web/src/types/ptz.ts @@ -0,0 +1,7 @@ +type PtzFeature = "pt" | "zoom" | "pt-r" | "zoom-r" | "zoom-a" | "pt-r-fov"; + +export type CameraPtzInfo = { + name: string; + features: PtzFeature[]; + presets: string[]; +}; diff --git a/web/src/views/live/LiveCameraView.tsx b/web/src/views/live/LiveCameraView.tsx index e5055b93d..5af60e7bc 100644 --- a/web/src/views/live/LiveCameraView.tsx +++ b/web/src/views/live/LiveCameraView.tsx @@ -1,10 +1,22 @@ +import { usePtzCommand } from "@/api/ws"; import LivePlayer from "@/components/player/LivePlayer"; import { Button } from "@/components/ui/button"; +import useKeyboardListener from "@/hooks/use-keyboard-listener"; import { CameraConfig } from "@/types/frigateConfig"; -import { useMemo } from "react"; +import { CameraPtzInfo } from "@/types/ptz"; +import React, { useCallback, useMemo } from "react"; import { isSafari } from "react-device-detect"; +import { BsThreeDotsVertical } from "react-icons/bs"; +import { + FaAngleDown, + FaAngleLeft, + FaAngleRight, + FaAngleUp, +} from "react-icons/fa"; import { IoMdArrowBack } from "react-icons/io"; +import { MdZoomIn, MdZoomOut } from "react-icons/md"; import { useNavigate } from "react-router-dom"; +import useSWR from "swr"; type LiveCameraViewProps = { camera: CameraConfig; @@ -43,7 +55,159 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) { preferredLiveMode={isSafari ? "webrtc" : "mse"} /> + {camera.onvif.host != "" && } ); } + +function PtzControlPanel({ camera }: { camera: string }) { + const { data: ptz } = useSWR(`${camera}/ptz/info`); + + const { payload: _, send: sendPtz } = usePtzCommand(camera); + + const onStop = useCallback( + (e: React.SyntheticEvent) => { + e.preventDefault(); + sendPtz("STOP"); + }, + [sendPtz], + ); + + useKeyboardListener( + ["ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown", "+", "-"], + (key, down, repeat) => { + if (repeat) { + return; + } + + if (!down) { + sendPtz("STOP"); + return; + } + + switch (key) { + case "ArrowLeft": + sendPtz("MOVE_LEFT"); + break; + case "ArrowRight": + sendPtz("MOVE_RIGHT"); + break; + case "ArrowUp": + sendPtz("MOVE_UP"); + break; + case "ArrowDown": + sendPtz("MOVE_DOWN"); + break; + case "+": + sendPtz("ZOOM_IN"); + break; + case "-": + sendPtz("ZOOM_OUT"); + break; + } + }, + ); + + return ( +
+ {ptz?.features?.includes("pt") && ( + <> + + + + + + )} + {ptz?.features?.includes("zoom") && ( + <> + + + + )} + {(ptz?.presets?.length ?? 0) > 0 && ( + + )} +
+ ); +}