feat: Add CameraPreviewModal component for live camera streaming
feat: Implement useAuth hook for user authentication management feat: Create useAutoRecording hook for managing automatic recording functionality feat: Develop AutoRecordingManager to handle automatic recording based on MQTT events test: Add test script to verify camera configuration API fix test: Create HTML page for testing camera configuration API and auto-recording fields
This commit is contained in:
524
API Documentations/streaming-api.http
Normal file
524
API Documentations/streaming-api.http
Normal file
@@ -0,0 +1,524 @@
|
||||
### USDA Vision Camera Streaming API
|
||||
###
|
||||
### CONFIGURATION:
|
||||
### - Production: http://vision:8000 (requires hostname setup)
|
||||
### - Development: http://localhost:8000
|
||||
### - Custom: Update @baseUrl below to match your setup
|
||||
###
|
||||
### This file contains streaming-specific API endpoints for live camera preview
|
||||
### Use with VS Code REST Client extension or similar tools.
|
||||
|
||||
# Base URL - Update to match your configuration
|
||||
@baseUrl = http://vision:8000
|
||||
# Alternative: @baseUrl = http://localhost:8000
|
||||
|
||||
### =============================================================================
|
||||
### STREAMING ENDPOINTS (NEW FUNCTIONALITY)
|
||||
### =============================================================================
|
||||
|
||||
### Start camera streaming for live preview
|
||||
### This creates a separate camera connection that doesn't interfere with recording
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Started streaming for camera camera1"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Stop camera streaming
|
||||
POST {{baseUrl}}/cameras/camera1/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Stopped streaming for camera camera1"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get live MJPEG stream (open in browser or use as img src)
|
||||
### This endpoint returns a continuous MJPEG stream
|
||||
### Content-Type: multipart/x-mixed-replace; boundary=frame
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
### Usage in HTML:
|
||||
# <img src="http://localhost:8000/cameras/camera1/stream" alt="Live Stream" />
|
||||
|
||||
### Usage in React:
|
||||
# <img src={`${apiBaseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`} />
|
||||
|
||||
###
|
||||
|
||||
### Start streaming for camera2
|
||||
POST {{baseUrl}}/cameras/camera2/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Get live stream for camera2
|
||||
GET {{baseUrl}}/cameras/camera2/stream
|
||||
|
||||
###
|
||||
|
||||
### Stop streaming for camera2
|
||||
POST {{baseUrl}}/cameras/camera2/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### =============================================================================
|
||||
### CONCURRENT OPERATIONS TESTING
|
||||
### =============================================================================
|
||||
|
||||
### Test Scenario: Streaming + Recording Simultaneously
|
||||
### This demonstrates that streaming doesn't block recording
|
||||
|
||||
### Step 1: Start streaming first
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Step 2: Start recording (while streaming continues)
|
||||
POST {{baseUrl}}/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "concurrent_test.avi"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Step 3: Check both are running
|
||||
GET {{baseUrl}}/cameras/camera1
|
||||
|
||||
### Expected Response shows both recording and streaming active:
|
||||
# {
|
||||
# "camera1": {
|
||||
# "name": "camera1",
|
||||
# "status": "connected",
|
||||
# "is_recording": true,
|
||||
# "current_recording_file": "concurrent_test.avi",
|
||||
# "recording_start_time": "2025-01-28T10:30:00.000Z"
|
||||
# }
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Step 4: Stop recording (streaming continues)
|
||||
POST {{baseUrl}}/cameras/camera1/stop-recording
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Step 5: Verify streaming still works
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
###
|
||||
|
||||
### Step 6: Stop streaming
|
||||
POST {{baseUrl}}/cameras/camera1/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### =============================================================================
|
||||
### MULTIPLE CAMERA STREAMING
|
||||
### =============================================================================
|
||||
|
||||
### Start streaming on multiple cameras simultaneously
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
POST {{baseUrl}}/cameras/camera2/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Check status of all cameras
|
||||
GET {{baseUrl}}/cameras
|
||||
|
||||
###
|
||||
|
||||
### Access multiple streams (open in separate browser tabs)
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
###
|
||||
|
||||
GET {{baseUrl}}/cameras/camera2/stream
|
||||
|
||||
###
|
||||
|
||||
### Stop all streaming
|
||||
POST {{baseUrl}}/cameras/camera1/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
POST {{baseUrl}}/cameras/camera2/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### =============================================================================
|
||||
### ERROR TESTING
|
||||
### =============================================================================
|
||||
|
||||
### Test with invalid camera name
|
||||
POST {{baseUrl}}/cameras/invalid_camera/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "detail": "Camera streamer not found: invalid_camera"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Test stream endpoint without starting stream first
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
### Expected: May return error or empty stream depending on camera state
|
||||
|
||||
###
|
||||
|
||||
### Test starting stream when camera is in error state
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### If camera has issues, expected response:
|
||||
# {
|
||||
# "success": false,
|
||||
# "message": "Failed to start streaming for camera camera1"
|
||||
# }
|
||||
|
||||
### =============================================================================
|
||||
### INTEGRATION EXAMPLES FOR AI ASSISTANTS
|
||||
### =============================================================================
|
||||
|
||||
### React Component Integration:
|
||||
# const CameraStream = ({ cameraName }) => {
|
||||
# const [isStreaming, setIsStreaming] = useState(false);
|
||||
#
|
||||
# const startStream = async () => {
|
||||
# const response = await fetch(`${baseUrl}/cameras/${cameraName}/start-stream`, {
|
||||
# method: 'POST'
|
||||
# });
|
||||
# if (response.ok) {
|
||||
# setIsStreaming(true);
|
||||
# }
|
||||
# };
|
||||
#
|
||||
# return (
|
||||
# <div>
|
||||
# <button onClick={startStream}>Start Stream</button>
|
||||
# {isStreaming && (
|
||||
# <img src={`${baseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`} />
|
||||
# )}
|
||||
# </div>
|
||||
# );
|
||||
# };
|
||||
|
||||
### JavaScript Fetch Example:
|
||||
# const streamAPI = {
|
||||
# async startStream(cameraName) {
|
||||
# const response = await fetch(`${baseUrl}/cameras/${cameraName}/start-stream`, {
|
||||
# method: 'POST',
|
||||
# headers: { 'Content-Type': 'application/json' }
|
||||
# });
|
||||
# return response.json();
|
||||
# },
|
||||
#
|
||||
# async stopStream(cameraName) {
|
||||
# const response = await fetch(`${baseUrl}/cameras/${cameraName}/stop-stream`, {
|
||||
# method: 'POST',
|
||||
# headers: { 'Content-Type': 'application/json' }
|
||||
# });
|
||||
# return response.json();
|
||||
# },
|
||||
#
|
||||
# getStreamUrl(cameraName) {
|
||||
# return `${baseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`;
|
||||
# }
|
||||
# };
|
||||
|
||||
### Vue.js Integration:
|
||||
# <template>
|
||||
# <div>
|
||||
# <button @click="startStream">Start Stream</button>
|
||||
# <img v-if="isStreaming" :src="streamUrl" />
|
||||
# </div>
|
||||
# </template>
|
||||
#
|
||||
# <script>
|
||||
# export default {
|
||||
# data() {
|
||||
# return {
|
||||
# isStreaming: false,
|
||||
# cameraName: 'camera1'
|
||||
# };
|
||||
# },
|
||||
# computed: {
|
||||
# streamUrl() {
|
||||
# return `${this.baseUrl}/cameras/${this.cameraName}/stream?t=${Date.now()}`;
|
||||
# }
|
||||
# },
|
||||
# methods: {
|
||||
# async startStream() {
|
||||
# const response = await fetch(`${this.baseUrl}/cameras/${this.cameraName}/start-stream`, {
|
||||
# method: 'POST'
|
||||
# });
|
||||
# if (response.ok) {
|
||||
# this.isStreaming = true;
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# };
|
||||
# </script>
|
||||
|
||||
### =============================================================================
|
||||
### TROUBLESHOOTING
|
||||
### =============================================================================
|
||||
|
||||
### If streams don't start:
|
||||
# 1. Check camera status: GET /cameras
|
||||
# 2. Verify system health: GET /health
|
||||
# 3. Test camera connection: POST /cameras/{name}/test-connection
|
||||
# 4. Check if camera is already recording (shouldn't matter, but good to know)
|
||||
|
||||
### If stream image doesn't load:
|
||||
# 1. Verify stream was started: POST /cameras/{name}/start-stream
|
||||
# 2. Check browser console for CORS errors
|
||||
# 3. Try accessing stream URL directly in browser
|
||||
# 4. Add timestamp to prevent caching: ?t=${Date.now()}
|
||||
|
||||
### If concurrent operations fail:
|
||||
# 1. This should work - streaming and recording use separate connections
|
||||
# 2. Check system logs for resource conflicts
|
||||
# 3. Verify sufficient system resources (CPU/Memory)
|
||||
# 4. Test with one camera first, then multiple
|
||||
|
||||
### Performance Notes:
|
||||
# - Streaming uses ~10 FPS by default (configurable)
|
||||
# - JPEG quality set to 70% (configurable)
|
||||
# - Each stream uses additional CPU/memory
|
||||
# - Multiple concurrent streams may impact performance
|
||||
|
||||
### =============================================================================
|
||||
### CAMERA CONFIGURATION ENDPOINTS (NEW)
|
||||
### =============================================================================
|
||||
|
||||
### Get camera configuration
|
||||
GET {{baseUrl}}/cameras/camera1/config
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "name": "camera1",
|
||||
# "machine_topic": "vibratory_conveyor",
|
||||
# "storage_path": "/storage/camera1",
|
||||
# "enabled": true,
|
||||
# "exposure_ms": 1.0,
|
||||
# "gain": 3.5,
|
||||
# "target_fps": 0,
|
||||
# "sharpness": 120,
|
||||
# "contrast": 110,
|
||||
# "saturation": 100,
|
||||
# "gamma": 100,
|
||||
# "noise_filter_enabled": true,
|
||||
# "denoise_3d_enabled": false,
|
||||
# "auto_white_balance": true,
|
||||
# "color_temperature_preset": 0,
|
||||
# "anti_flicker_enabled": true,
|
||||
# "light_frequency": 1,
|
||||
# "bit_depth": 8,
|
||||
# "hdr_enabled": false,
|
||||
# "hdr_gain_mode": 0
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Update basic camera settings (real-time, no restart required)
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"target_fps": 10.0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update image quality settings
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"sharpness": 150,
|
||||
"contrast": 120,
|
||||
"saturation": 110,
|
||||
"gamma": 90
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update advanced settings
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 2
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Enable HDR mode
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"hdr_enabled": true,
|
||||
"hdr_gain_mode": 1
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update noise reduction settings (requires restart)
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": true
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Apply configuration (restart camera with new settings)
|
||||
POST {{baseUrl}}/cameras/camera1/apply-config
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Configuration applied to camera camera1"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get camera2 configuration
|
||||
GET {{baseUrl}}/cameras/camera2/config
|
||||
|
||||
###
|
||||
|
||||
### Update camera2 for outdoor lighting
|
||||
PUT {{baseUrl}}/cameras/camera2/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 0.5,
|
||||
"gain": 2.0,
|
||||
"sharpness": 130,
|
||||
"contrast": 115,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1
|
||||
}
|
||||
|
||||
### =============================================================================
|
||||
### CONFIGURATION TESTING SCENARIOS
|
||||
### =============================================================================
|
||||
|
||||
### Scenario 1: Low light optimization
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 5.0,
|
||||
"gain": 8.0,
|
||||
"noise_filter_enabled": true,
|
||||
"denoise_3d_enabled": true
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Scenario 2: High speed capture
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 0.2,
|
||||
"gain": 1.0,
|
||||
"target_fps": 30.0,
|
||||
"sharpness": 180
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Scenario 3: Color accuracy for food inspection
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 1,
|
||||
"saturation": 120,
|
||||
"contrast": 105,
|
||||
"gamma": 95
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Scenario 4: HDR for high contrast scenes
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"hdr_enabled": true,
|
||||
"hdr_gain_mode": 2,
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.0
|
||||
}
|
||||
|
||||
### =============================================================================
|
||||
### ERROR TESTING FOR CONFIGURATION
|
||||
### =============================================================================
|
||||
|
||||
### Test invalid camera name
|
||||
GET {{baseUrl}}/cameras/invalid_camera/config
|
||||
|
||||
###
|
||||
|
||||
### Test invalid exposure range
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 2000.0
|
||||
}
|
||||
|
||||
### Expected: HTTP 422 validation error
|
||||
|
||||
###
|
||||
|
||||
### Test invalid gain range
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"gain": 50.0
|
||||
}
|
||||
|
||||
### Expected: HTTP 422 validation error
|
||||
|
||||
###
|
||||
|
||||
### Test empty configuration update
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
|
||||
### Expected: HTTP 400 "No configuration updates provided"
|
||||
Reference in New Issue
Block a user