Support Controlling PTZ Cameras Via WebUI (#4715)

* Add support for ptz commands via websocket

* Fix startup issues

* Fix bugs

* Set config manually

* Add more commands

* Add presets

* Add zooming

* Fixes

* Set name

* Cleanup

* Add ability to set presets from UI

* Add ability to set preset from UI

* Cleanup for errors

* Ui tweaks

* Add visual design for pan / tilt

* Add pan/tilt support

* Support zooming

* Try to set wsdl

* Fix duplicate logs

* Catch auth errors

* Don't init onvif for disabled cameras

* Fix layout sizing

* Don't comment out

* Fix formatting

* Add ability to control camera with keyboard shortcuts

* Disallow user selection

* Fix mobile pressing

* Remove logs

* Substitute onvif password

* Add ptz controls ot birdseye

* Put wsdl back

* Add padding

* Formatting

* Catch onvif error

* Optimize layout for mobile and web

* Place ptz controls next to birdseye view in large layout

* Fix pt support

* Center text titles

* Update tests

* Update docs

* Write camera docs for PTZ

* Add MQTT docs for PTZ

* Add ptz info docs for http

* Fix test

* Make half width when full screen

* Fix preset panel logic

* Fix parsing

* Update mqtt.md

* Catch preset error

* Add onvif example to docs

* Remove template example from main camera docs
This commit is contained in:
Nicolas Mowen
2023-04-26 05:08:53 -06:00
committed by GitHub
parent 0d16bd0144
commit 43ade86796
21 changed files with 769 additions and 16 deletions

View File

@@ -6,6 +6,8 @@ import Heading from '../components/Heading';
import WebRtcPlayer from '../components/WebRtcPlayer';
import MsePlayer from '../components/MsePlayer';
import useSWR from 'swr';
import { useMemo } from 'preact/hooks';
import CameraControlPanel from '../components/CameraControlPanel';
export default function Birdseye() {
const { data: config } = useSWR('config');
@@ -16,6 +18,16 @@ export default function Birdseye() {
);
const sourceValues = ['mse', 'webrtc', 'jsmpeg'];
const ptzCameras = useMemo(() => {
if (!config) {
return [];
}
return Object.entries(config.cameras)
.filter(([_, conf]) => conf.onvif?.host)
.map(([_, camera]) => camera.name);
}, [config]);
if (!config || !sourceIsLoaded) {
return <ActivityIndicator />;
}
@@ -25,7 +37,7 @@ export default function Birdseye() {
if ('MediaSource' in window) {
player = (
<Fragment>
<div className="max-w-5xl">
<div className="max-w-5xl xl:w-1/2">
<MsePlayer camera="birdseye" />
</div>
</Fragment>
@@ -42,7 +54,7 @@ export default function Birdseye() {
} else if (viewSource == 'webrtc' && config.birdseye.restream) {
player = (
<Fragment>
<div className="max-w-5xl">
<div className="max-w-5xl xl:w-1/2">
<WebRtcPlayer camera="birdseye" />
</div>
</Fragment>
@@ -50,7 +62,7 @@ export default function Birdseye() {
} else {
player = (
<Fragment>
<div className="max-w-7xl">
<div className="max-w-7xl xl:w-1/2">
<JSMpegPlayer camera="birdseye" />
</div>
</Fragment>
@@ -79,7 +91,21 @@ export default function Birdseye() {
)}
</div>
{player}
<div className="xl:flex justify-between">
{player}
{ptzCameras && (
<div className="dark:bg-gray-800 shadow-md hover:shadow-lg rounded-lg transition-shadow p-4 w-full sm:w-min xl:h-min xl:w-1/2">
<Heading size="sm">Control Panel</Heading>
{ptzCameras.map((camera) => (
<div className="p-4" key={camera}>
<Heading size="lg">{camera.replaceAll('_', ' ')}</Heading>
<CameraControlPanel camera={camera} />
</div>
))}
</div>
)}
</div>
</div>
);
}