Industrielle PTZ-kameraer krever ofte proprietære kontrollprogrammer eller komplekse ONVIF-klienter. En webbasert kontrollstasjon gir sentralisert styring av flere kameraer fra én grensesnitt.
Arkitektur og krav

Løsningen består av en backend-tjeneste som kommuniserer med kameraenes API og et webgrensesnitt for operatørstyring. PTZ-kameraer støtter typisk HTTP-kommandoer for pan, tilt, zoom og preset-posisjoner.
Krav til systemet:
- Sanntids PTZ-kontroll med minimal forsinkelse
- Støtte for multiple kameraer samtidig
- Preset-lagring og -gjenoppkalling
- Sesjonsbasert tilstandshåndtering
Backend API-implementering
Backend håndterer kamerakommunikasjon og tilstandssynkronisering. Implementer en FastAPI-tjeneste som proxy for kamerakommandoer:
from fastapi import FastAPI, HTTPException
import httpx
import asyncio
app = FastAPI()
class CameraController:
def __init__(self, camera_ip: str, username: str, password: str):
self.base_url = f"http://{camera_ip}"
self.auth = (username, password)
self.session = httpx.AsyncClient()
async def ptz_command(self, command: str, value: int = 0):
url = f"{self.base_url}/cgi-bin/ptz.cgi"
params = {"cmd": command, "value": value}
response = await self.session.get(url, params=params, auth=self.auth)
return response.status_code == 200
Implementer endepunkter for alle PTZ-funksjoner og legg til feilhåndtering for nettverkstimeouts.
Fanebasert webgrensesnitt

Frontend organiseres i faner per kamera med dedikerte kontroller. Bruk WebSocket for sanntidsoppdateringer:
class PTZController {
constructor(cameraId) {
this.cameraId = cameraId;
this.websocket = new WebSocket(`ws://localhost:8000/ws/${cameraId}`);
this.setupEventListeners();
}
async sendPTZCommand(command, value = 0) {
const response = await fetch(`/api/camera/${this.cameraId}/ptz`, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({command, value})
});
return response.ok;
}
setupEventListeners() {
document.getElementById('pan-left').addEventListener('mousedown',
() => this.startContinuousCommand('pan_left'));
document.getElementById('pan-left').addEventListener('mouseup',
() => this.stopContinuousCommand());
}
}
Sesjonsbasert tilstandslagring
Implementer sesjonslagring for å bevare kameraposisjoner og innstillinger mellom økter. Bruk Redis eller lokal cache:
import redis
import json
class SessionManager:
def __init__(self):
self.redis_client = redis.Redis(host='localhost', port=6379, db=0)
def save_camera_state(self, session_id: str, camera_id: str, state: dict):
key = f"session:{session_id}:camera:{camera_id}"
self.redis_client.setex(key, 3600, json.dumps(state))
def get_camera_state(self, session_id: str, camera_id: str):
key = f"session:{session_id}:camera:{camera_id}"
data = self.redis_client.get(key)
return json.loads(data) if data else {}
Lagre preset-posisjoner, zoom-nivåer og siste kjente koordinater automatisk. Implementer også manuell lagring av navngitte presets.
Deployment og sikkerhet
Deploy kontrollstasjonen i et isolert nettsegment med tilgang til kameraenes VLAN. Bruk HTTPS og autentisering:
server {
listen 443 ssl;
server_name camera-control.local;
ssl_certificate /etc/ssl/certs/camera-control.crt;
ssl_certificate_key /etc/ssl/private/camera-control.key;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
location /ws/ {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Begrens tilgang til kontrollstasjonen via firewall-regler og implementer rolle-basert tilgangskontroll for operatører.


