Chore: rename api->camera-management-api and web->management-dashboard-web-app; update compose, ignore, README references
This commit is contained in:
542
camera-management-api/ai_agent/references/api-endpoints.http
Normal file
542
camera-management-api/ai_agent/references/api-endpoints.http
Normal file
@@ -0,0 +1,542 @@
|
||||
###############################################################################
|
||||
# USDA Vision Camera System - Complete API Endpoints Documentation
|
||||
#
|
||||
# CONFIGURATION:
|
||||
# - Default Base URL: http://localhost:8000 (local development)
|
||||
# - Production Base URL: http://vision:8000 (when using hostname 'vision')
|
||||
# - Custom hostname: Update @baseUrl variable below
|
||||
#
|
||||
# HOSTNAME SETUP:
|
||||
# To use 'vision' hostname instead of 'localhost':
|
||||
# 1. Add to /etc/hosts: 127.0.0.1 vision
|
||||
# 2. Or configure DNS to point 'vision' to the server IP
|
||||
# 3. Update camera_preview.html: API_BASE = 'http://vision:8000'
|
||||
###############################################################################
|
||||
|
||||
# Base URL Configuration - Change this to match your setup
|
||||
@baseUrl = http://vision:8000
|
||||
# Alternative configurations:
|
||||
# @baseUrl = http://localhost:8000 # Local development
|
||||
# @baseUrl = http://192.168.1.100:8000 # Specific IP address
|
||||
# @baseUrl = http://your-server:8000 # Custom hostname
|
||||
|
||||
###############################################################################
|
||||
# CONFIGURATION GUIDE
|
||||
###############################################################################
|
||||
|
||||
### HOSTNAME CONFIGURATION OPTIONS:
|
||||
|
||||
# Option 1: Using 'vision' hostname (recommended for production)
|
||||
# - Requires hostname resolution setup
|
||||
# - Add to /etc/hosts: 127.0.0.1 vision
|
||||
# - Or configure DNS: vision -> server IP address
|
||||
# - Update camera_preview.html: API_BASE = 'http://vision:8000'
|
||||
# - Set @baseUrl = http://vision:8000
|
||||
|
||||
# Option 2: Using localhost (development)
|
||||
# - Works immediately on local machine
|
||||
# - Set @baseUrl = http://localhost:8000
|
||||
# - Update camera_preview.html: API_BASE = 'http://localhost:8000'
|
||||
|
||||
# Option 3: Using specific IP address
|
||||
# - Replace with actual server IP
|
||||
# - Set @baseUrl = http://192.168.1.100:8000
|
||||
# - Update camera_preview.html: API_BASE = 'http://192.168.1.100:8000'
|
||||
|
||||
# Option 4: Custom hostname
|
||||
# - Configure DNS or /etc/hosts for custom name
|
||||
# - Set @baseUrl = http://your-custom-name:8000
|
||||
# - Update camera_preview.html: API_BASE = 'http://your-custom-name:8000'
|
||||
|
||||
### NETWORK CONFIGURATION:
|
||||
# - Default port: 8000
|
||||
# - CORS enabled for all origins (configure for production)
|
||||
# - No authentication required (add if needed)
|
||||
|
||||
### CLIENT CONFIGURATION FILES TO UPDATE:
|
||||
# 1. camera_preview.html - Update API_BASE constant
|
||||
# 2. React projects - Update apiConfig.baseUrl
|
||||
# 3. This file - Update @baseUrl variable
|
||||
# 4. Any custom scripts - Update base URL
|
||||
|
||||
### TESTING CONNECTIVITY:
|
||||
# Test if the API is reachable:
|
||||
GET {{baseUrl}}/health
|
||||
|
||||
###############################################################################
|
||||
# SYSTEM ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Root endpoint - API information
|
||||
GET {{baseUrl}}/
|
||||
# Response: SuccessResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "USDA Vision Camera System API",
|
||||
# "data": null,
|
||||
# "timestamp": "2025-07-28T12:00:00"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Health check
|
||||
GET http://localhost:8000/health
|
||||
# Response: Simple health status
|
||||
# {
|
||||
# "status": "healthy",
|
||||
# "timestamp": "2025-07-28T12:00:00"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get system status
|
||||
GET http://localhost:8000/system/status
|
||||
# Response: SystemStatusResponse
|
||||
# {
|
||||
# "system_started": true,
|
||||
# "mqtt_connected": true,
|
||||
# "last_mqtt_message": "2025-07-28T12:00:00",
|
||||
# "machines": {
|
||||
# "vibratory_conveyor": {
|
||||
# "name": "vibratory_conveyor",
|
||||
# "state": "off",
|
||||
# "last_updated": "2025-07-28T12:00:00"
|
||||
# }
|
||||
# },
|
||||
# "cameras": {
|
||||
# "camera1": {
|
||||
# "name": "camera1",
|
||||
# "status": "connected",
|
||||
# "is_recording": false
|
||||
# }
|
||||
# },
|
||||
# "active_recordings": 0,
|
||||
# "total_recordings": 5,
|
||||
# "uptime_seconds": 3600.5
|
||||
# }
|
||||
|
||||
###############################################################################
|
||||
# MACHINE ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Get all machines status
|
||||
GET http://localhost:8000/machines
|
||||
# Response: Dict[str, MachineStatusResponse]
|
||||
# {
|
||||
# "vibratory_conveyor": {
|
||||
# "name": "vibratory_conveyor",
|
||||
# "state": "off",
|
||||
# "last_updated": "2025-07-28T12:00:00",
|
||||
# "last_message": "off",
|
||||
# "mqtt_topic": "vision/vibratory_conveyor/state"
|
||||
# },
|
||||
# "blower_separator": {
|
||||
# "name": "blower_separator",
|
||||
# "state": "on",
|
||||
# "last_updated": "2025-07-28T12:00:00",
|
||||
# "last_message": "on",
|
||||
# "mqtt_topic": "vision/blower_separator/state"
|
||||
# }
|
||||
# }
|
||||
|
||||
###############################################################################
|
||||
# MQTT ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Get MQTT status and statistics
|
||||
GET http://localhost:8000/mqtt/status
|
||||
# Response: MQTTStatusResponse
|
||||
# {
|
||||
# "connected": true,
|
||||
# "broker_host": "192.168.1.110",
|
||||
# "broker_port": 1883,
|
||||
# "subscribed_topics": [
|
||||
# "vision/vibratory_conveyor/state",
|
||||
# "vision/blower_separator/state"
|
||||
# ],
|
||||
# "last_message_time": "2025-07-28T12:00:00",
|
||||
# "message_count": 42,
|
||||
# "error_count": 0,
|
||||
# "uptime_seconds": 3600.5
|
||||
# }
|
||||
|
||||
### Get recent MQTT events history
|
||||
GET http://localhost:8000/mqtt/events
|
||||
# Optional query parameter: limit (default: 5, max: 50)
|
||||
# Response: MQTTEventsHistoryResponse
|
||||
# {
|
||||
# "events": [
|
||||
# {
|
||||
# "machine_name": "vibratory_conveyor",
|
||||
# "topic": "vision/vibratory_conveyor/state",
|
||||
# "payload": "on",
|
||||
# "normalized_state": "on",
|
||||
# "timestamp": "2025-07-28T15:30:45.123456",
|
||||
# "message_number": 15
|
||||
# },
|
||||
# {
|
||||
# "machine_name": "blower_separator",
|
||||
# "topic": "vision/blower_separator/state",
|
||||
# "payload": "off",
|
||||
# "normalized_state": "off",
|
||||
# "timestamp": "2025-07-28T15:29:12.654321",
|
||||
# "message_number": 14
|
||||
# }
|
||||
# ],
|
||||
# "total_events": 15,
|
||||
# "last_updated": "2025-07-28T15:30:45.123456"
|
||||
# }
|
||||
|
||||
### Get recent MQTT events with custom limit
|
||||
GET http://localhost:8000/mqtt/events?limit=10
|
||||
|
||||
###############################################################################
|
||||
# CAMERA ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Get all cameras status
|
||||
GET http://localhost:8000/cameras
|
||||
# Response: Dict[str, CameraStatusResponse]
|
||||
# {
|
||||
# "camera1": {
|
||||
# "name": "camera1",
|
||||
# "status": "connected",
|
||||
# "is_recording": false,
|
||||
# "last_checked": "2025-07-28T12:00:00",
|
||||
# "last_error": null,
|
||||
# "device_info": {
|
||||
# "friendly_name": "MindVision Camera",
|
||||
# "serial_number": "ABC123"
|
||||
# },
|
||||
# "current_recording_file": null,
|
||||
# "recording_start_time": null
|
||||
# }
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get specific camera status
|
||||
GET http://localhost:8000/cameras/camera1/status
|
||||
### Get specific camera status
|
||||
GET http://localhost:8000/cameras/camera2/status
|
||||
# Response: CameraStatusResponse (same as above for single camera)
|
||||
|
||||
###############################################################################
|
||||
# RECORDING CONTROL ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Start recording (with all optional parameters)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "test_recording.avi",
|
||||
"exposure_ms": 1.5,
|
||||
"gain": 3.0,
|
||||
"fps": 10.0
|
||||
}
|
||||
# Request Parameters (all optional):
|
||||
# - filename: string - Custom filename (datetime prefix auto-added)
|
||||
# - exposure_ms: float - Exposure time in milliseconds
|
||||
# - gain: float - Camera gain value
|
||||
# - fps: float - Target frames per second (0 = maximum speed, omit = use config default)
|
||||
#
|
||||
# Response: StartRecordingResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Recording started for camera1",
|
||||
# "filename": "20250728_120000_test_recording.avi"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Start recording (minimal - only filename)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "simple_test.avi"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording (only camera settings)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"fps": 0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording (empty body - all defaults)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
|
||||
###
|
||||
|
||||
### Stop recording
|
||||
POST http://localhost:8000/cameras/camera1/stop-recording
|
||||
POST http://localhost:8000/cameras/camera2/stop-recording
|
||||
# No request body required
|
||||
# Response: StopRecordingResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Recording stopped for camera1",
|
||||
# "duration_seconds": 45.2
|
||||
# }
|
||||
|
||||
###############################################################################
|
||||
# AUTO-RECORDING CONTROL ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Enable auto-recording for a camera
|
||||
POST http://localhost:8000/cameras/camera1/auto-recording/enable
|
||||
POST http://localhost:8000/cameras/camera2/auto-recording/enable
|
||||
# No request body required
|
||||
# Response: AutoRecordingConfigResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Auto-recording enabled for camera1",
|
||||
# "camera_name": "camera1",
|
||||
# "enabled": true
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Disable auto-recording for a camera
|
||||
POST http://localhost:8000/cameras/camera1/auto-recording/disable
|
||||
POST http://localhost:8000/cameras/camera2/auto-recording/disable
|
||||
# No request body required
|
||||
# Response: AutoRecordingConfigResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Auto-recording disabled for camera1",
|
||||
# "camera_name": "camera1",
|
||||
# "enabled": false
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get auto-recording manager status
|
||||
GET http://localhost:8000/auto-recording/status
|
||||
# Response: AutoRecordingStatusResponse
|
||||
# {
|
||||
# "running": true,
|
||||
# "auto_recording_enabled": true,
|
||||
# "retry_queue": {},
|
||||
# "enabled_cameras": ["camera1", "camera2"]
|
||||
# }
|
||||
|
||||
###############################################################################
|
||||
# CAMERA RECOVERY & DIAGNOSTICS ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Test camera connection
|
||||
POST http://localhost:8000/cameras/camera1/test-connection
|
||||
POST http://localhost:8000/cameras/camera2/test-connection
|
||||
# No request body required
|
||||
# Response: CameraTestResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Camera camera1 connection test passed",
|
||||
# "camera_name": "camera1",
|
||||
# "timestamp": "2025-07-28T12:00:00"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Reconnect camera (soft recovery)
|
||||
POST http://localhost:8000/cameras/camera1/reconnect
|
||||
POST http://localhost:8000/cameras/camera2/reconnect
|
||||
# No request body required
|
||||
# Response: CameraRecoveryResponse
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Camera camera1 reconnected successfully",
|
||||
# "camera_name": "camera1",
|
||||
# "operation": "reconnect",
|
||||
# "timestamp": "2025-07-28T12:00:00"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Restart camera grab process
|
||||
POST http://localhost:8000/cameras/camera1/restart-grab
|
||||
POST http://localhost:8000/cameras/camera2/restart-grab
|
||||
# Response: CameraRecoveryResponse (same structure as reconnect)
|
||||
|
||||
###
|
||||
|
||||
### Reset camera timestamp
|
||||
POST http://localhost:8000/cameras/camera1/reset-timestamp
|
||||
POST http://localhost:8000/cameras/camera2/reset-timestamp
|
||||
# Response: CameraRecoveryResponse (same structure as reconnect)
|
||||
|
||||
###
|
||||
|
||||
### Full camera reset (hard recovery)
|
||||
POST http://localhost:8000/cameras/camera1/full-reset
|
||||
### Full camera reset (hard recovery)
|
||||
POST http://localhost:8000/cameras/camera2/full-reset
|
||||
# Response: CameraRecoveryResponse (same structure as reconnect)
|
||||
|
||||
###
|
||||
|
||||
### Reinitialize failed camera
|
||||
POST http://localhost:8000/cameras/camera1/reinitialize
|
||||
POST http://localhost:8000/cameras/camera2/reinitialize
|
||||
# Response: CameraRecoveryResponse (same structure as reconnect)
|
||||
|
||||
###############################################################################
|
||||
# RECORDING SESSIONS ENDPOINT
|
||||
###############################################################################
|
||||
|
||||
### Get all recording sessions
|
||||
GET http://localhost:8000/recordings
|
||||
# Response: Dict[str, RecordingInfoResponse]
|
||||
# {
|
||||
# "rec_001": {
|
||||
# "camera_name": "camera1",
|
||||
# "filename": "20250728_120000_test.avi",
|
||||
# "start_time": "2025-07-28T12:00:00",
|
||||
# "state": "completed",
|
||||
# "end_time": "2025-07-28T12:05:00",
|
||||
# "file_size_bytes": 1048576,
|
||||
# "frame_count": 1500,
|
||||
# "duration_seconds": 300.0,
|
||||
# "error_message": null
|
||||
# }
|
||||
# }
|
||||
|
||||
###############################################################################
|
||||
# STORAGE ENDPOINTS
|
||||
###############################################################################
|
||||
|
||||
### Get storage statistics
|
||||
GET http://localhost:8000/storage/stats
|
||||
# Response: StorageStatsResponse
|
||||
# {
|
||||
# "base_path": "/storage",
|
||||
# "total_files": 25,
|
||||
# "total_size_bytes": 52428800,
|
||||
# "cameras": {
|
||||
# "camera1": {
|
||||
# "file_count": 15,
|
||||
# "total_size_bytes": 31457280
|
||||
# }
|
||||
# },
|
||||
# "disk_usage": {
|
||||
# "total": 1000000000,
|
||||
# "used": 500000000,
|
||||
# "free": 500000000
|
||||
# }
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get recording files list (with filters)
|
||||
POST http://localhost:8000/storage/files
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"start_date": "2025-07-25T00:00:00",
|
||||
"end_date": "2025-07-28T23:59:59",
|
||||
"limit": 50
|
||||
}
|
||||
# Request Parameters (all optional):
|
||||
# - camera_name: string - Filter by specific camera
|
||||
# - start_date: string (ISO format) - Filter files from this date
|
||||
# - end_date: string (ISO format) - Filter files until this date
|
||||
# - limit: integer (max 1000, default 100) - Maximum number of files to return
|
||||
#
|
||||
# Response: FileListResponse
|
||||
# {
|
||||
# "files": [
|
||||
# {
|
||||
# "filename": "20250728_120000_test.avi",
|
||||
# "camera_name": "camera1",
|
||||
# "file_size_bytes": 1048576,
|
||||
# "created_date": "2025-07-28T12:00:00",
|
||||
# "duration_seconds": 300.0
|
||||
# }
|
||||
# ],
|
||||
# "total_count": 1
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get all files (no camera filter)
|
||||
POST http://localhost:8000/storage/files
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"limit": 100
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Cleanup old storage files
|
||||
POST http://localhost:8000/storage/cleanup
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"max_age_days": 7
|
||||
}
|
||||
# Request Parameters:
|
||||
# - max_age_days: integer (optional) - Remove files older than this many days
|
||||
# If not provided, uses config default (30 days)
|
||||
#
|
||||
# Response: CleanupResponse
|
||||
# {
|
||||
# "files_removed": 5,
|
||||
# "bytes_freed": 10485760,
|
||||
# "errors": []
|
||||
# }
|
||||
|
||||
###############################################################################
|
||||
# ERROR RESPONSES
|
||||
###############################################################################
|
||||
# All endpoints may return ErrorResponse on failure:
|
||||
# {
|
||||
# "error": "Error description",
|
||||
# "details": "Additional error details",
|
||||
# "timestamp": "2025-07-28T12:00:00"
|
||||
# }
|
||||
# Common HTTP status codes:
|
||||
# - 200: Success
|
||||
# - 400: Bad Request (invalid parameters)
|
||||
# - 404: Not Found (camera/resource not found)
|
||||
# - 500: Internal Server Error
|
||||
# - 503: Service Unavailable (camera manager not available)
|
||||
|
||||
###############################################################################
|
||||
# NOTES
|
||||
###############################################################################
|
||||
# 1. All timestamps are in ISO 8601 format
|
||||
# 2. File sizes are in bytes
|
||||
# 3. Camera names: "camera1", "camera2"
|
||||
# 4. Machine names: "vibratory_conveyor", "blower_separator"
|
||||
# 5. FPS behavior:
|
||||
# - fps > 0: Capture at specified frame rate
|
||||
# - fps = 0: Capture at MAXIMUM possible speed (no delay)
|
||||
# - fps omitted: Uses camera config default
|
||||
# 6. Filenames automatically get datetime prefix: YYYYMMDD_HHMMSS_filename.avi
|
||||
# 7. Recovery endpoints should be used in order: test-connection → reconnect → restart-grab → full-reset → reinitialize
|
||||
|
||||
|
||||
|
||||
### Start streaming for camera1
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-stream
|
||||
|
||||
# View live stream (open in browser)
|
||||
# http://localhost:8000/cameras/camera1/stream
|
||||
|
||||
### Stop streaming
|
||||
curl -X POST http://localhost:8000/cameras/camera1/stop-stream
|
||||
308
camera-management-api/ai_agent/references/api-tests.http
Normal file
308
camera-management-api/ai_agent/references/api-tests.http
Normal file
@@ -0,0 +1,308 @@
|
||||
### Get system status
|
||||
GET http://localhost:8000/system/status
|
||||
|
||||
###
|
||||
|
||||
### Get camera1 status
|
||||
GET http://localhost:8000/cameras/camera1/status
|
||||
|
||||
###
|
||||
|
||||
### Get camera2 status
|
||||
GET http://localhost:8000/cameras/camera2/status
|
||||
|
||||
###
|
||||
### RECORDING TESTS
|
||||
### Note: All filenames will automatically have datetime prefix added
|
||||
### Format: YYYYMMDD_HHMMSS_filename.avi (or auto-generated if no filename)
|
||||
###
|
||||
### FPS Behavior:
|
||||
### - fps > 0: Capture at specified frame rate
|
||||
### - fps = 0: Capture at MAXIMUM possible speed (no delay between frames)
|
||||
### - fps omitted: Uses camera config default (usually 3.0 fps)
|
||||
### - Video files saved with 30 FPS metadata when fps=0 for proper playback
|
||||
###
|
||||
|
||||
### Start recording camera1 (basic)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "manual22_test_cam1.avi"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera1 (with camera settings)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "test_with_settings.avi",
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"fps": 0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera2 (basic)
|
||||
POST http://localhost:8000/cameras/camera2/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "manual_test_cam2.avi"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera2 (with different settings)
|
||||
POST http://localhost:8000/cameras/camera2/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "high_fps_test.avi",
|
||||
"exposure_ms": 0.5,
|
||||
"gain": 2.5,
|
||||
"fps": 10.0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera1 (no filename, only settings)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 1.5,
|
||||
"gain": 3.0,
|
||||
"fps": 7.0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera1 (only filename, no settings)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "just_filename_test.avi"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera2 (only exposure setting)
|
||||
POST http://localhost:8000/cameras/camera2/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 3.0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera1 (only gain setting)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"gain": 5.5
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera2 (only fps setting)
|
||||
POST http://localhost:8000/cameras/camera2/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"fps": 15.0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera1 (maximum fps - no delay)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "max_fps_test.avi",
|
||||
"fps": 0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera2 (maximum fps with settings)
|
||||
POST http://localhost:8000/cameras/camera2/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "max_fps_low_exposure.avi",
|
||||
"exposure_ms": 0.1,
|
||||
"gain": 1.0,
|
||||
"fps": 0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Start recording camera1 (empty body - all defaults)
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
|
||||
###
|
||||
|
||||
### Stop camera1 recording
|
||||
POST http://localhost:8000/cameras/camera1/stop-recording
|
||||
|
||||
###
|
||||
|
||||
### Stop camera2 recording
|
||||
POST http://localhost:8000/cameras/camera2/stop-recording
|
||||
|
||||
###
|
||||
### SYSTEM STATUS AND STORAGE TESTS
|
||||
###
|
||||
|
||||
### Get all cameras status
|
||||
GET http://localhost:8000/cameras
|
||||
|
||||
###
|
||||
|
||||
### Get storage statistics
|
||||
GET http://localhost:8000/storage/stats
|
||||
|
||||
###
|
||||
|
||||
### Get storage files list
|
||||
POST http://localhost:8000/storage/files
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"limit": 10
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Get storage files list (all cameras)
|
||||
POST http://localhost:8000/storage/files
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"limit": 20
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Health check
|
||||
GET http://localhost:8000/health
|
||||
|
||||
###
|
||||
### CAMERA RECOVERY AND DIAGNOSTICS TESTS
|
||||
###
|
||||
### These endpoints help recover cameras that have failed to initialize or lost connection.
|
||||
###
|
||||
### Recovery Methods (in order of severity):
|
||||
### 1. test-connection: Test if camera connection is working
|
||||
### 2. reconnect: Soft reconnection using CameraReConnect()
|
||||
### 3. restart-grab: Restart grab process using CameraRestartGrab()
|
||||
### 4. reset-timestamp: Reset camera timestamp using CameraRstTimeStamp()
|
||||
### 5. full-reset: Hard reset - uninitialize and reinitialize camera
|
||||
### 6. reinitialize: Complete reinitialization for cameras that never initialized
|
||||
###
|
||||
### Recommended troubleshooting order:
|
||||
### 1. Start with test-connection to diagnose the issue
|
||||
### 2. Try reconnect first (most common fix)
|
||||
### 3. If reconnect fails, try restart-grab
|
||||
### 4. If still failing, try full-reset
|
||||
### 5. Use reinitialize only for cameras that failed initial setup
|
||||
###
|
||||
|
||||
### Test camera1 connection
|
||||
POST http://localhost:8000/cameras/camera1/test-connection
|
||||
|
||||
###
|
||||
|
||||
### Test camera2 connection
|
||||
POST http://localhost:8000/cameras/camera2/test-connection
|
||||
|
||||
###
|
||||
|
||||
### Reconnect camera1 (soft recovery)
|
||||
POST http://localhost:8000/cameras/camera1/reconnect
|
||||
|
||||
###
|
||||
|
||||
### Reconnect camera2 (soft recovery)
|
||||
POST http://localhost:8000/cameras/camera2/reconnect
|
||||
|
||||
###
|
||||
|
||||
### Restart camera1 grab process
|
||||
POST http://localhost:8000/cameras/camera1/restart-grab
|
||||
|
||||
###
|
||||
|
||||
### Restart camera2 grab process
|
||||
POST http://localhost:8000/cameras/camera2/restart-grab
|
||||
|
||||
###
|
||||
|
||||
### Reset camera1 timestamp
|
||||
POST http://localhost:8000/cameras/camera1/reset-timestamp
|
||||
|
||||
###
|
||||
|
||||
### Reset camera2 timestamp
|
||||
POST http://localhost:8000/cameras/camera2/reset-timestamp
|
||||
|
||||
###
|
||||
|
||||
### Full reset camera1 (hard recovery - uninitialize and reinitialize)
|
||||
POST http://localhost:8000/cameras/camera1/full-reset
|
||||
|
||||
###
|
||||
|
||||
### Full reset camera2 (hard recovery - uninitialize and reinitialize)
|
||||
POST http://localhost:8000/cameras/camera2/full-reset
|
||||
|
||||
###
|
||||
|
||||
### Reinitialize camera1 (for cameras that failed to initialize)
|
||||
POST http://localhost:8000/cameras/camera1/reinitialize
|
||||
|
||||
###
|
||||
|
||||
### Reinitialize camera2 (for cameras that failed to initialize)
|
||||
POST http://localhost:8000/cameras/camera2/reinitialize
|
||||
|
||||
###
|
||||
### RECOVERY WORKFLOW EXAMPLES
|
||||
###
|
||||
|
||||
### Example 1: Basic troubleshooting workflow for camera1
|
||||
### Step 1: Test connection
|
||||
POST http://localhost:8000/cameras/camera1/test-connection
|
||||
|
||||
### Step 2: If test fails, try reconnect
|
||||
# POST http://localhost:8000/cameras/camera1/reconnect
|
||||
|
||||
### Step 3: If reconnect fails, try restart grab
|
||||
# POST http://localhost:8000/cameras/camera1/restart-grab
|
||||
|
||||
### Step 4: If still failing, try full reset
|
||||
# POST http://localhost:8000/cameras/camera1/full-reset
|
||||
|
||||
### Step 5: If camera never initialized, try reinitialize
|
||||
# POST http://localhost:8000/cameras/camera1/reinitialize
|
||||
|
||||
###
|
||||
|
||||
### Example 2: Quick recovery sequence for camera2
|
||||
### Try reconnect first (most common fix)
|
||||
POST http://localhost:8000/cameras/camera2/reconnect
|
||||
|
||||
### If that doesn't work, try full reset
|
||||
# POST http://localhost:8000/cameras/camera2/full-reset
|
||||
367
camera-management-api/ai_agent/references/camera-api.types.ts
Normal file
367
camera-management-api/ai_agent/references/camera-api.types.ts
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* TypeScript definitions for USDA Vision Camera System API
|
||||
*
|
||||
* This file provides complete type definitions for AI assistants
|
||||
* to integrate the camera streaming functionality into React/TypeScript projects.
|
||||
*/
|
||||
|
||||
// =============================================================================
|
||||
// BASE CONFIGURATION
|
||||
// =============================================================================
|
||||
|
||||
export interface ApiConfig {
|
||||
baseUrl: string;
|
||||
timeout?: number;
|
||||
refreshInterval?: number;
|
||||
}
|
||||
|
||||
export const defaultApiConfig: ApiConfig = {
|
||||
baseUrl: 'http://vision:8000', // Production default, change to 'http://localhost:8000' for development
|
||||
timeout: 10000,
|
||||
refreshInterval: 30000,
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// CAMERA TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraDeviceInfo {
|
||||
friendly_name?: string;
|
||||
port_type?: string;
|
||||
serial_number?: string;
|
||||
device_index?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface CameraInfo {
|
||||
name: string;
|
||||
status: 'connected' | 'disconnected' | 'error' | 'not_found' | 'available';
|
||||
is_recording: boolean;
|
||||
last_checked: string; // ISO date string
|
||||
last_error?: string | null;
|
||||
device_info?: CameraDeviceInfo;
|
||||
current_recording_file?: string | null;
|
||||
recording_start_time?: string | null; // ISO date string
|
||||
}
|
||||
|
||||
export interface CameraListResponse {
|
||||
[cameraName: string]: CameraInfo;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// STREAMING TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface StreamStartRequest {
|
||||
// No body required - camera name is in URL path
|
||||
}
|
||||
|
||||
export interface StreamStartResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface StreamStopRequest {
|
||||
// No body required - camera name is in URL path
|
||||
}
|
||||
|
||||
export interface StreamStopResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface StreamStatus {
|
||||
isStreaming: boolean;
|
||||
streamUrl?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// RECORDING TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface StartRecordingRequest {
|
||||
filename?: string;
|
||||
exposure_ms?: number;
|
||||
gain?: number;
|
||||
fps?: number;
|
||||
}
|
||||
|
||||
export interface StartRecordingResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
filename?: string;
|
||||
}
|
||||
|
||||
export interface StopRecordingResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SYSTEM TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface SystemStatusResponse {
|
||||
status: string;
|
||||
uptime: string;
|
||||
api_server_running: boolean;
|
||||
camera_manager_running: boolean;
|
||||
mqtt_client_connected: boolean;
|
||||
total_cameras: number;
|
||||
active_recordings: number;
|
||||
active_streams?: number;
|
||||
}
|
||||
|
||||
export interface HealthResponse {
|
||||
status: 'healthy' | 'unhealthy';
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ERROR TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface ApiError {
|
||||
detail: string;
|
||||
status_code?: number;
|
||||
}
|
||||
|
||||
export interface StreamError extends Error {
|
||||
type: 'network' | 'api' | 'stream' | 'timeout';
|
||||
cameraName: string;
|
||||
originalError?: Error;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// HOOK TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface UseCameraStreamResult {
|
||||
isStreaming: boolean;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
startStream: () => Promise<{ success: boolean; error?: string }>;
|
||||
stopStream: () => Promise<{ success: boolean; error?: string }>;
|
||||
getStreamUrl: () => string;
|
||||
refreshStream: () => void;
|
||||
}
|
||||
|
||||
export interface UseCameraListResult {
|
||||
cameras: CameraListResponse;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refreshCameras: () => Promise<void>;
|
||||
}
|
||||
|
||||
export interface UseCameraRecordingResult {
|
||||
isRecording: boolean;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
currentFile: string | null;
|
||||
startRecording: (options?: StartRecordingRequest) => Promise<{ success: boolean; error?: string }>;
|
||||
stopRecording: () => Promise<{ success: boolean; error?: string }>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMPONENT PROPS TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraStreamProps {
|
||||
cameraName: string;
|
||||
apiConfig?: ApiConfig;
|
||||
autoStart?: boolean;
|
||||
onStreamStart?: (cameraName: string) => void;
|
||||
onStreamStop?: (cameraName: string) => void;
|
||||
onError?: (error: StreamError) => void;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface CameraDashboardProps {
|
||||
apiConfig?: ApiConfig;
|
||||
cameras?: string[]; // If provided, only show these cameras
|
||||
showRecordingControls?: boolean;
|
||||
showStreamingControls?: boolean;
|
||||
refreshInterval?: number;
|
||||
onCameraSelect?: (cameraName: string) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface CameraControlsProps {
|
||||
cameraName: string;
|
||||
apiConfig?: ApiConfig;
|
||||
showRecording?: boolean;
|
||||
showStreaming?: boolean;
|
||||
onAction?: (action: 'start-stream' | 'stop-stream' | 'start-recording' | 'stop-recording', cameraName: string) => void;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// API CLIENT TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraApiClient {
|
||||
// System endpoints
|
||||
getHealth(): Promise<HealthResponse>;
|
||||
getSystemStatus(): Promise<SystemStatusResponse>;
|
||||
|
||||
// Camera endpoints
|
||||
getCameras(): Promise<CameraListResponse>;
|
||||
getCameraStatus(cameraName: string): Promise<CameraInfo>;
|
||||
testCameraConnection(cameraName: string): Promise<{ success: boolean; message: string }>;
|
||||
|
||||
// Streaming endpoints
|
||||
startStream(cameraName: string): Promise<StreamStartResponse>;
|
||||
stopStream(cameraName: string): Promise<StreamStopResponse>;
|
||||
getStreamUrl(cameraName: string): string;
|
||||
|
||||
// Recording endpoints
|
||||
startRecording(cameraName: string, options?: StartRecordingRequest): Promise<StartRecordingResponse>;
|
||||
stopRecording(cameraName: string): Promise<StopRecordingResponse>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// UTILITY TYPES
|
||||
// =============================================================================
|
||||
|
||||
export type CameraAction = 'start-stream' | 'stop-stream' | 'start-recording' | 'stop-recording' | 'test-connection';
|
||||
|
||||
export interface CameraActionResult {
|
||||
success: boolean;
|
||||
message: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface StreamingState {
|
||||
[cameraName: string]: {
|
||||
isStreaming: boolean;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
lastStarted?: Date;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RecordingState {
|
||||
[cameraName: string]: {
|
||||
isRecording: boolean;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
currentFile: string | null;
|
||||
startTime?: Date;
|
||||
};
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EVENT TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraEvent {
|
||||
type: 'stream-started' | 'stream-stopped' | 'stream-error' | 'recording-started' | 'recording-stopped' | 'recording-error';
|
||||
cameraName: string;
|
||||
timestamp: Date;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export type CameraEventHandler = (event: CameraEvent) => void;
|
||||
|
||||
// =============================================================================
|
||||
// CONFIGURATION TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface StreamConfig {
|
||||
fps: number;
|
||||
quality: number; // 1-100
|
||||
timeout: number;
|
||||
retryAttempts: number;
|
||||
retryDelay: number;
|
||||
}
|
||||
|
||||
export interface CameraStreamConfig extends StreamConfig {
|
||||
cameraName: string;
|
||||
autoReconnect: boolean;
|
||||
maxReconnectAttempts: number;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CONTEXT TYPES (for React Context)
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraContextValue {
|
||||
cameras: CameraListResponse;
|
||||
streamingState: StreamingState;
|
||||
recordingState: RecordingState;
|
||||
apiClient: CameraApiClient;
|
||||
|
||||
// Actions
|
||||
startStream: (cameraName: string) => Promise<CameraActionResult>;
|
||||
stopStream: (cameraName: string) => Promise<CameraActionResult>;
|
||||
startRecording: (cameraName: string, options?: StartRecordingRequest) => Promise<CameraActionResult>;
|
||||
stopRecording: (cameraName: string) => Promise<CameraActionResult>;
|
||||
refreshCameras: () => Promise<void>;
|
||||
|
||||
// State
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EXAMPLE USAGE TYPES
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Example usage in React component:
|
||||
*
|
||||
* ```typescript
|
||||
* import { CameraStreamProps, UseCameraStreamResult } from './camera-api.types';
|
||||
*
|
||||
* const CameraStream: React.FC<CameraStreamProps> = ({
|
||||
* cameraName,
|
||||
* apiConfig = defaultApiConfig,
|
||||
* autoStart = false,
|
||||
* onStreamStart,
|
||||
* onStreamStop,
|
||||
* onError
|
||||
* }) => {
|
||||
* const {
|
||||
* isStreaming,
|
||||
* loading,
|
||||
* error,
|
||||
* startStream,
|
||||
* stopStream,
|
||||
* getStreamUrl
|
||||
* }: UseCameraStreamResult = useCameraStream(cameraName, apiConfig);
|
||||
*
|
||||
* // Component implementation...
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example API client usage:
|
||||
*
|
||||
* ```typescript
|
||||
* const apiClient: CameraApiClient = new CameraApiClientImpl(defaultApiConfig);
|
||||
*
|
||||
* // Start streaming
|
||||
* const result = await apiClient.startStream('camera1');
|
||||
* if (result.success) {
|
||||
* const streamUrl = apiClient.getStreamUrl('camera1');
|
||||
* // Use streamUrl in img tag
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example hook usage:
|
||||
*
|
||||
* ```typescript
|
||||
* const MyComponent = () => {
|
||||
* const { cameras, loading, error, refreshCameras } = useCameraList();
|
||||
* const { isStreaming, startStream, stopStream } = useCameraStream('camera1');
|
||||
*
|
||||
* // Component logic...
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
|
||||
export default {};
|
||||
543
camera-management-api/ai_agent/references/streaming-api.http
Normal file
543
camera-management-api/ai_agent/references/streaming-api.http
Normal file
@@ -0,0 +1,543 @@
|
||||
### 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,
|
||||
# "auto_start_recording_enabled": true,
|
||||
# "auto_recording_max_retries": 3,
|
||||
# "auto_recording_retry_delay_seconds": 2,
|
||||
# "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,
|
||||
# "wb_red_gain": 1.0,
|
||||
# "wb_green_gain": 1.0,
|
||||
# "wb_blue_gain": 1.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
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update white balance RGB gains (manual white balance)
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"auto_white_balance": false,
|
||||
"wb_red_gain": 1.2,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.8
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### 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