Add mock mode for WebUI development
- Add mock API classes for camera search and stream discovery - Add mock mode toggle via ?mock=true URL parameter - Add visual mock mode indicator badge - Add dev-server.sh script for local development - Mock data includes 10 diverse streams (FFMPEG, ONVIF, JPEG, MJPEG, HLS, HTTP_VIDEO)
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
// Mock implementation of CameraSearchAPI for development
|
||||
export class MockCameraAPI {
|
||||
constructor() {
|
||||
this.mockCameras = [
|
||||
{ brand: "Hikvision", model: "DS-2CD2042WD-I" },
|
||||
{ brand: "Hikvision", model: "DS-2CD2142FWD-I" },
|
||||
{ brand: "Hikvision", model: "DS-2CD2032-I" },
|
||||
{ brand: "Hikvision", model: "DS-2CD2385G1-I" },
|
||||
{ brand: "Dahua", model: "IPC-HFW4431R-Z" },
|
||||
{ brand: "Dahua", model: "IPC-HDBW4433R-ZS" },
|
||||
{ brand: "Dahua", model: "DH-IPC-HFW2431S-S-S2" },
|
||||
{ brand: "Dahua", model: "IPC-HDW2531T-AS-S2" },
|
||||
{ brand: "Axis", model: "M3046-V" },
|
||||
{ brand: "Axis", model: "P3245-LVE" },
|
||||
{ brand: "Axis", model: "M5525-E" },
|
||||
{ brand: "Uniview", model: "IPC322SR3-DVS28-F" },
|
||||
{ brand: "Uniview", model: "IPC2124SR3-DPF40" },
|
||||
{ brand: "Reolink", model: "RLC-410" },
|
||||
{ brand: "Reolink", model: "RLC-520A" },
|
||||
{ brand: "Reolink", model: "RLC-810A" },
|
||||
{ brand: "TP-Link", model: "VIGI C300HP-4" },
|
||||
{ brand: "TP-Link", model: "VIGI C540V" },
|
||||
{ brand: "Amcrest", model: "IP8M-2496EW" },
|
||||
{ brand: "Amcrest", model: "IP4M-1041B" },
|
||||
{ brand: "Foscam", model: "FI9900P" },
|
||||
{ brand: "Foscam", model: "R5" },
|
||||
];
|
||||
}
|
||||
|
||||
async search(query, limit = 10) {
|
||||
// Simulate network delay
|
||||
await this.delay(150);
|
||||
|
||||
const lowerQuery = query.toLowerCase();
|
||||
const filtered = this.mockCameras.filter(camera => {
|
||||
const searchText = `${camera.brand} ${camera.model}`.toLowerCase();
|
||||
return searchText.includes(lowerQuery);
|
||||
});
|
||||
|
||||
return {
|
||||
cameras: filtered.slice(0, limit),
|
||||
total: filtered.length
|
||||
};
|
||||
}
|
||||
|
||||
delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
// Mock implementation of StreamDiscoveryAPI for development
|
||||
export class MockStreamAPI {
|
||||
constructor() {
|
||||
this.mockStreams = [
|
||||
{
|
||||
url: "rtsp://192.168.1.100:554/Streaming/Channels/101",
|
||||
path: "/Streaming/Channels/101",
|
||||
type: "FFMPEG",
|
||||
resolution: "1920x1080",
|
||||
codec: "H.264",
|
||||
fps: 25,
|
||||
bitrate: 4096000,
|
||||
has_audio: true
|
||||
},
|
||||
{
|
||||
url: "http://192.168.1.100/snap.jpg",
|
||||
path: "/snap.jpg",
|
||||
type: "JPEG",
|
||||
resolution: "1920x1080",
|
||||
codec: "JPEG",
|
||||
fps: 1,
|
||||
bitrate: 0,
|
||||
has_audio: false
|
||||
},
|
||||
{
|
||||
url: "http://192.168.1.100/video.mjpg",
|
||||
path: "/video.mjpg",
|
||||
type: "MJPEG",
|
||||
resolution: "1280x720",
|
||||
codec: "MJPEG",
|
||||
fps: 10,
|
||||
bitrate: 2048000,
|
||||
has_audio: false
|
||||
},
|
||||
{
|
||||
url: "http://192.168.1.100/stream/live.m3u8",
|
||||
path: "/stream/live.m3u8",
|
||||
type: "HLS",
|
||||
resolution: "1920x1080",
|
||||
codec: "H.264",
|
||||
fps: 25,
|
||||
bitrate: 3072000,
|
||||
has_audio: true
|
||||
},
|
||||
{
|
||||
url: "http://192.168.1.100/videostream.cgi?user=admin&pwd=12345",
|
||||
path: "/videostream.cgi?user=admin&pwd=12345",
|
||||
type: "HTTP_VIDEO",
|
||||
resolution: "1280x960",
|
||||
codec: "H.264",
|
||||
fps: 20,
|
||||
bitrate: 2048000,
|
||||
has_audio: false
|
||||
},
|
||||
{
|
||||
url: "rtsp://192.168.1.100:554/Streaming/Channels/102",
|
||||
path: "/Streaming/Channels/102",
|
||||
type: "FFMPEG",
|
||||
resolution: "640x480",
|
||||
codec: "H.264",
|
||||
fps: 15,
|
||||
bitrate: 512000,
|
||||
has_audio: false
|
||||
},
|
||||
{
|
||||
url: "rtsp://192.168.1.100:554/cam/realmonitor?channel=1&subtype=0",
|
||||
path: "/cam/realmonitor?channel=1&subtype=0",
|
||||
type: "ONVIF",
|
||||
resolution: "2560x1440",
|
||||
codec: "H.265",
|
||||
fps: 30,
|
||||
bitrate: 6144000,
|
||||
has_audio: true
|
||||
},
|
||||
{
|
||||
url: "rtsp://192.168.1.100:554/h264Preview_01_main",
|
||||
path: "/h264Preview_01_main",
|
||||
type: "FFMPEG",
|
||||
resolution: "1920x1080",
|
||||
codec: "H.264",
|
||||
fps: 20,
|
||||
bitrate: 3072000,
|
||||
has_audio: true
|
||||
},
|
||||
{
|
||||
url: "rtsp://192.168.1.100:554/live/ch0",
|
||||
path: "/live/ch0",
|
||||
type: "ONVIF",
|
||||
resolution: "2688x1520",
|
||||
codec: "H.265",
|
||||
fps: 25,
|
||||
bitrate: 5120000,
|
||||
has_audio: true
|
||||
},
|
||||
{
|
||||
url: "rtsp://192.168.1.100:554/stream1",
|
||||
path: "/stream1",
|
||||
type: "FFMPEG",
|
||||
resolution: "3840x2160",
|
||||
codec: "H.265",
|
||||
fps: 30,
|
||||
bitrate: 8192000,
|
||||
has_audio: true
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
discover(request, callbacks) {
|
||||
const totalToScan = 150;
|
||||
const streamsToFind = this.mockStreams;
|
||||
let tested = 0;
|
||||
let found = 0;
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
// Simulate progressive discovery
|
||||
const interval = setInterval(() => {
|
||||
const increment = Math.floor(Math.random() * 8) + 3;
|
||||
tested = Math.min(tested + increment, totalToScan);
|
||||
const remaining = totalToScan - tested;
|
||||
|
||||
// Send progress event
|
||||
if (callbacks.onProgress) {
|
||||
callbacks.onProgress({
|
||||
tested: tested,
|
||||
found: found,
|
||||
remaining: remaining
|
||||
});
|
||||
}
|
||||
|
||||
// Randomly find streams
|
||||
if (found < streamsToFind.length && Math.random() > 0.6) {
|
||||
const stream = streamsToFind[found];
|
||||
found++;
|
||||
|
||||
if (callbacks.onStreamFound) {
|
||||
callbacks.onStreamFound({
|
||||
stream: stream
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Complete when done
|
||||
if (tested >= totalToScan) {
|
||||
clearInterval(interval);
|
||||
|
||||
// Send any remaining streams
|
||||
while (found < streamsToFind.length) {
|
||||
const stream = streamsToFind[found];
|
||||
found++;
|
||||
|
||||
if (callbacks.onStreamFound) {
|
||||
callbacks.onStreamFound({
|
||||
stream: stream
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const duration = (Date.now() - startTime) / 1000;
|
||||
|
||||
if (callbacks.onComplete) {
|
||||
callbacks.onComplete({
|
||||
total_tested: totalToScan,
|
||||
total_found: found,
|
||||
duration: duration
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 400);
|
||||
}
|
||||
|
||||
close() {
|
||||
// Nothing to close in mock mode
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user