Get ptz working

This commit is contained in:
Nicolas Mowen 2024-03-01 12:58:03 -07:00
parent 750502c629
commit 2be8b91c15
3 changed files with 173 additions and 13 deletions

View File

@ -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 useOverlayState from "@/hooks/use-overlay-state";
import { usePersistence } from "@/hooks/use-persistence";
import { FrigateConfig } from "@/types/frigateConfig"; import { FrigateConfig } from "@/types/frigateConfig";
import { ReviewSegment } from "@/types/review";
import LiveCameraView from "@/views/live/LiveCameraView"; import LiveCameraView from "@/views/live/LiveCameraView";
import LiveDashboardView from "@/views/live/LiveDashboardView"; import LiveDashboardView from "@/views/live/LiveDashboardView";
import { useCallback, useEffect, useMemo, useState } from "react"; import { useMemo } from "react";
import { isDesktop, isMobile, isSafari } from "react-device-detect";
import { CiGrid2H, CiGrid31 } from "react-icons/ci";
import useSWR from "swr"; import useSWR from "swr";
function Live() { function Live() {

7
web/src/types/ptz.ts Normal file
View File

@ -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[];
};

View File

@ -1,10 +1,22 @@
import { usePtzCommand } from "@/api/ws";
import LivePlayer from "@/components/player/LivePlayer"; import LivePlayer from "@/components/player/LivePlayer";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import useKeyboardListener from "@/hooks/use-keyboard-listener";
import { CameraConfig } from "@/types/frigateConfig"; 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 { 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 { IoMdArrowBack } from "react-icons/io";
import { MdZoomIn, MdZoomOut } from "react-icons/md";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import useSWR from "swr";
type LiveCameraViewProps = { type LiveCameraViewProps = {
camera: CameraConfig; camera: CameraConfig;
@ -43,7 +55,159 @@ export default function LiveCameraView({ camera }: LiveCameraViewProps) {
preferredLiveMode={isSafari ? "webrtc" : "mse"} preferredLiveMode={isSafari ? "webrtc" : "mse"}
/> />
</div> </div>
{camera.onvif.host != "" && <PtzControlPanel camera={camera.name} />}
</div> </div>
</div> </div>
); );
} }
function PtzControlPanel({ camera }: { camera: string }) {
const { data: ptz } = useSWR<CameraPtzInfo>(`${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 (
<div className="absolute left-[50%] -translate-x-[50%] bottom-[10%] flex items-center gap-1">
{ptz?.features?.includes("pt") && (
<>
<Button
onMouseDown={(e) => {
e.preventDefault();
sendPtz("MOVE_LEFT");
}}
onTouchStart={(e) => {
e.preventDefault();
sendPtz("MOVE_LEFT");
}}
onMouseUp={onStop}
onTouchEnd={onStop}
>
<FaAngleLeft />
</Button>
<Button
onMouseDown={(e) => {
e.preventDefault();
sendPtz("MOVE_UP");
}}
onTouchStart={(e) => {
e.preventDefault();
sendPtz("MOVE_UP");
}}
onMouseUp={onStop}
onTouchEnd={onStop}
>
<FaAngleUp />
</Button>
<Button
onMouseDown={(e) => {
e.preventDefault();
sendPtz("MOVE_DOWN");
}}
onTouchStart={(e) => {
e.preventDefault();
sendPtz("MOVE_DOWN");
}}
onMouseUp={onStop}
onTouchEnd={onStop}
>
<FaAngleDown />
</Button>
<Button
onMouseDown={(e) => {
e.preventDefault();
sendPtz("MOVE_RIGHT");
}}
onTouchStart={(e) => {
e.preventDefault();
sendPtz("MOVE_RIGHT");
}}
onMouseUp={onStop}
onTouchEnd={onStop}
>
<FaAngleRight />
</Button>
</>
)}
{ptz?.features?.includes("zoom") && (
<>
<Button
onMouseDown={(e) => {
e.preventDefault();
sendPtz("ZOOM_IN");
}}
onTouchStart={(e) => {
e.preventDefault();
sendPtz("ZOOM_IN");
}}
onMouseUp={onStop}
onTouchEnd={onStop}
>
<MdZoomIn />
</Button>
<Button
onMouseDown={(e) => {
e.preventDefault();
sendPtz("ZOOM_OUT");
}}
onTouchStart={(e) => {
e.preventDefault();
sendPtz("ZOOM_OUT");
}}
onMouseUp={onStop}
onTouchEnd={onStop}
>
<MdZoomOut />
</Button>
</>
)}
{(ptz?.presets?.length ?? 0) > 0 && (
<Button>
<BsThreeDotsVertical />
</Button>
)}
</div>
);
}