Chore: rename api->camera-management-api and web->management-dashboard-web-app; update compose, ignore, README references
This commit is contained in:
415
camera-management-api/docs/AI_AGENT_VIDEO_INTEGRATION_GUIDE.md
Normal file
415
camera-management-api/docs/AI_AGENT_VIDEO_INTEGRATION_GUIDE.md
Normal file
@@ -0,0 +1,415 @@
|
||||
# 🤖 AI Agent Video Integration Guide
|
||||
|
||||
This guide provides comprehensive step-by-step instructions for AI agents and external systems to successfully integrate with the USDA Vision Camera System's video streaming functionality.
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
The USDA Vision Camera System provides a complete video streaming API that allows AI agents to:
|
||||
- Browse and select videos from multiple cameras
|
||||
- Stream videos with seeking capabilities
|
||||
- Generate thumbnails for preview
|
||||
- Access video metadata and technical information
|
||||
|
||||
## 🔗 API Base Configuration
|
||||
|
||||
### Connection Details
|
||||
```bash
|
||||
# Default API Base URL
|
||||
API_BASE_URL="http://localhost:8000"
|
||||
|
||||
# For remote access, replace with actual server IP/hostname
|
||||
API_BASE_URL="http://192.168.1.100:8000"
|
||||
```
|
||||
|
||||
### Authentication
|
||||
**⚠️ IMPORTANT: No authentication is currently required.**
|
||||
- All endpoints are publicly accessible
|
||||
- No API keys or tokens needed
|
||||
- CORS is enabled for web browser integration
|
||||
|
||||
## 📋 Step-by-Step Integration Workflow
|
||||
|
||||
### Step 1: Verify System Connectivity
|
||||
```bash
|
||||
# Test basic connectivity
|
||||
curl -f "${API_BASE_URL}/health" || echo "❌ System not accessible"
|
||||
|
||||
# Check system status
|
||||
curl "${API_BASE_URL}/system/status"
|
||||
```
|
||||
|
||||
**Expected Response:**
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2025-08-05T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: List Available Videos
|
||||
```bash
|
||||
# Get all videos with metadata
|
||||
curl "${API_BASE_URL}/videos/?include_metadata=true&limit=50"
|
||||
|
||||
# Filter by specific camera
|
||||
curl "${API_BASE_URL}/videos/?camera_name=camera1&include_metadata=true"
|
||||
|
||||
# Filter by date range
|
||||
curl "${API_BASE_URL}/videos/?start_date=2025-08-04T00:00:00&end_date=2025-08-05T23:59:59"
|
||||
```
|
||||
|
||||
**Response Structure:**
|
||||
```json
|
||||
{
|
||||
"videos": [
|
||||
{
|
||||
"file_id": "camera1_auto_blower_separator_20250804_143022.mp4",
|
||||
"camera_name": "camera1",
|
||||
"filename": "camera1_auto_blower_separator_20250804_143022.mp4",
|
||||
"file_size_bytes": 31457280,
|
||||
"format": "mp4",
|
||||
"status": "completed",
|
||||
"created_at": "2025-08-04T14:30:22",
|
||||
"start_time": "2025-08-04T14:30:22",
|
||||
"end_time": "2025-08-04T14:32:22",
|
||||
"machine_trigger": "blower_separator",
|
||||
"is_streamable": true,
|
||||
"needs_conversion": false,
|
||||
"metadata": {
|
||||
"duration_seconds": 120.5,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"fps": 30.0,
|
||||
"codec": "mp4v",
|
||||
"bitrate": 5000000,
|
||||
"aspect_ratio": 1.777
|
||||
}
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Select and Validate Video
|
||||
```bash
|
||||
# Get detailed video information
|
||||
FILE_ID="camera1_auto_blower_separator_20250804_143022.mp4"
|
||||
curl "${API_BASE_URL}/videos/${FILE_ID}"
|
||||
|
||||
# Validate video is playable
|
||||
curl -X POST "${API_BASE_URL}/videos/${FILE_ID}/validate"
|
||||
|
||||
# Get streaming technical details
|
||||
curl "${API_BASE_URL}/videos/${FILE_ID}/info"
|
||||
```
|
||||
|
||||
### Step 4: Generate Video Thumbnail
|
||||
```bash
|
||||
# Generate thumbnail at 5 seconds, 320x240 resolution
|
||||
curl "${API_BASE_URL}/videos/${FILE_ID}/thumbnail?timestamp=5.0&width=320&height=240" \
|
||||
--output "thumbnail_${FILE_ID}.jpg"
|
||||
|
||||
# Generate multiple thumbnails for preview
|
||||
for timestamp in 1 30 60 90; do
|
||||
curl "${API_BASE_URL}/videos/${FILE_ID}/thumbnail?timestamp=${timestamp}&width=160&height=120" \
|
||||
--output "preview_${timestamp}s.jpg"
|
||||
done
|
||||
```
|
||||
|
||||
### Step 5: Stream Video Content
|
||||
```bash
|
||||
# Stream entire video
|
||||
curl "${API_BASE_URL}/videos/${FILE_ID}/stream" --output "video.mp4"
|
||||
|
||||
# Stream specific byte range (for seeking)
|
||||
curl -H "Range: bytes=0-1048575" \
|
||||
"${API_BASE_URL}/videos/${FILE_ID}/stream" \
|
||||
--output "video_chunk.mp4"
|
||||
|
||||
# Test range request support
|
||||
curl -I -H "Range: bytes=0-1023" \
|
||||
"${API_BASE_URL}/videos/${FILE_ID}/stream"
|
||||
```
|
||||
|
||||
## 🔧 Programming Language Examples
|
||||
|
||||
### Python Integration
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
from typing import List, Dict, Optional
|
||||
|
||||
class USDAVideoClient:
|
||||
def __init__(self, base_url: str = "http://localhost:8000"):
|
||||
self.base_url = base_url.rstrip('/')
|
||||
self.session = requests.Session()
|
||||
|
||||
def list_videos(self, camera_name: Optional[str] = None,
|
||||
include_metadata: bool = True, limit: int = 50) -> Dict:
|
||||
"""List available videos with optional filtering."""
|
||||
params = {
|
||||
'include_metadata': include_metadata,
|
||||
'limit': limit
|
||||
}
|
||||
if camera_name:
|
||||
params['camera_name'] = camera_name
|
||||
|
||||
response = self.session.get(f"{self.base_url}/videos/", params=params)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
def get_video_info(self, file_id: str) -> Dict:
|
||||
"""Get detailed video information."""
|
||||
response = self.session.get(f"{self.base_url}/videos/{file_id}")
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
def get_thumbnail(self, file_id: str, timestamp: float = 1.0,
|
||||
width: int = 320, height: int = 240) -> bytes:
|
||||
"""Generate and download video thumbnail."""
|
||||
params = {
|
||||
'timestamp': timestamp,
|
||||
'width': width,
|
||||
'height': height
|
||||
}
|
||||
response = self.session.get(
|
||||
f"{self.base_url}/videos/{file_id}/thumbnail",
|
||||
params=params
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.content
|
||||
|
||||
def stream_video_range(self, file_id: str, start_byte: int,
|
||||
end_byte: int) -> bytes:
|
||||
"""Stream specific byte range of video."""
|
||||
headers = {'Range': f'bytes={start_byte}-{end_byte}'}
|
||||
response = self.session.get(
|
||||
f"{self.base_url}/videos/{file_id}/stream",
|
||||
headers=headers
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.content
|
||||
|
||||
def validate_video(self, file_id: str) -> bool:
|
||||
"""Validate that video is accessible and playable."""
|
||||
response = self.session.post(f"{self.base_url}/videos/{file_id}/validate")
|
||||
response.raise_for_status()
|
||||
return response.json().get('is_valid', False)
|
||||
|
||||
# Usage example
|
||||
client = USDAVideoClient("http://192.168.1.100:8000")
|
||||
|
||||
# List videos from camera1
|
||||
videos = client.list_videos(camera_name="camera1")
|
||||
print(f"Found {videos['total_count']} videos")
|
||||
|
||||
# Select first video
|
||||
if videos['videos']:
|
||||
video = videos['videos'][0]
|
||||
file_id = video['file_id']
|
||||
|
||||
# Validate video
|
||||
if client.validate_video(file_id):
|
||||
print(f"✅ Video {file_id} is valid")
|
||||
|
||||
# Get thumbnail
|
||||
thumbnail = client.get_thumbnail(file_id, timestamp=5.0)
|
||||
with open(f"thumbnail_{file_id}.jpg", "wb") as f:
|
||||
f.write(thumbnail)
|
||||
|
||||
# Stream first 1MB
|
||||
chunk = client.stream_video_range(file_id, 0, 1048575)
|
||||
print(f"Downloaded {len(chunk)} bytes")
|
||||
```
|
||||
|
||||
### JavaScript/Node.js Integration
|
||||
```javascript
|
||||
class USDAVideoClient {
|
||||
constructor(baseUrl = 'http://localhost:8000') {
|
||||
this.baseUrl = baseUrl.replace(/\/$/, '');
|
||||
}
|
||||
|
||||
async listVideos(options = {}) {
|
||||
const params = new URLSearchParams({
|
||||
include_metadata: options.includeMetadata || true,
|
||||
limit: options.limit || 50
|
||||
});
|
||||
|
||||
if (options.cameraName) {
|
||||
params.append('camera_name', options.cameraName);
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.baseUrl}/videos/?${params}`);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async getVideoInfo(fileId) {
|
||||
const response = await fetch(`${this.baseUrl}/videos/${fileId}`);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async getThumbnail(fileId, options = {}) {
|
||||
const params = new URLSearchParams({
|
||||
timestamp: options.timestamp || 1.0,
|
||||
width: options.width || 320,
|
||||
height: options.height || 240
|
||||
});
|
||||
|
||||
const response = await fetch(
|
||||
`${this.baseUrl}/videos/${fileId}/thumbnail?${params}`
|
||||
);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
return response.blob();
|
||||
}
|
||||
|
||||
async validateVideo(fileId) {
|
||||
const response = await fetch(
|
||||
`${this.baseUrl}/videos/${fileId}/validate`,
|
||||
{ method: 'POST' }
|
||||
);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
const result = await response.json();
|
||||
return result.is_valid;
|
||||
}
|
||||
|
||||
getStreamUrl(fileId) {
|
||||
return `${this.baseUrl}/videos/${fileId}/stream`;
|
||||
}
|
||||
}
|
||||
|
||||
// Usage example
|
||||
const client = new USDAVideoClient('http://192.168.1.100:8000');
|
||||
|
||||
async function integrateWithVideos() {
|
||||
try {
|
||||
// List videos
|
||||
const videos = await client.listVideos({ cameraName: 'camera1' });
|
||||
console.log(`Found ${videos.total_count} videos`);
|
||||
|
||||
if (videos.videos.length > 0) {
|
||||
const video = videos.videos[0];
|
||||
const fileId = video.file_id;
|
||||
|
||||
// Validate video
|
||||
const isValid = await client.validateVideo(fileId);
|
||||
if (isValid) {
|
||||
console.log(`✅ Video ${fileId} is valid`);
|
||||
|
||||
// Get thumbnail
|
||||
const thumbnail = await client.getThumbnail(fileId, {
|
||||
timestamp: 5.0,
|
||||
width: 320,
|
||||
height: 240
|
||||
});
|
||||
|
||||
// Create video element for playback
|
||||
const videoElement = document.createElement('video');
|
||||
videoElement.controls = true;
|
||||
videoElement.src = client.getStreamUrl(fileId);
|
||||
document.body.appendChild(videoElement);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Integration error:', error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🚨 Error Handling
|
||||
|
||||
### Common HTTP Status Codes
|
||||
```bash
|
||||
# Success responses
|
||||
200 # OK - Request successful
|
||||
206 # Partial Content - Range request successful
|
||||
|
||||
# Client error responses
|
||||
400 # Bad Request - Invalid parameters
|
||||
404 # Not Found - Video file doesn't exist
|
||||
416 # Range Not Satisfiable - Invalid range request
|
||||
|
||||
# Server error responses
|
||||
500 # Internal Server Error - Failed to process video
|
||||
503 # Service Unavailable - Video module not available
|
||||
```
|
||||
|
||||
### Error Response Format
|
||||
```json
|
||||
{
|
||||
"detail": "Video camera1_recording_20250804_143022.avi not found"
|
||||
}
|
||||
```
|
||||
|
||||
### Robust Error Handling Example
|
||||
```python
|
||||
def safe_video_operation(client, file_id):
|
||||
try:
|
||||
# Validate video first
|
||||
if not client.validate_video(file_id):
|
||||
return {"error": "Video is not valid or accessible"}
|
||||
|
||||
# Get video info
|
||||
video_info = client.get_video_info(file_id)
|
||||
|
||||
# Check if streamable
|
||||
if not video_info.get('is_streamable', False):
|
||||
return {"error": "Video is not streamable"}
|
||||
|
||||
return {"success": True, "video_info": video_info}
|
||||
|
||||
except requests.exceptions.HTTPError as e:
|
||||
if e.response.status_code == 404:
|
||||
return {"error": "Video not found"}
|
||||
elif e.response.status_code == 416:
|
||||
return {"error": "Invalid range request"}
|
||||
else:
|
||||
return {"error": f"HTTP error: {e.response.status_code}"}
|
||||
except requests.exceptions.ConnectionError:
|
||||
return {"error": "Cannot connect to video server"}
|
||||
except Exception as e:
|
||||
return {"error": f"Unexpected error: {str(e)}"}
|
||||
```
|
||||
|
||||
## ✅ Integration Checklist
|
||||
|
||||
### Pre-Integration
|
||||
- [ ] Verify network connectivity to USDA Vision Camera System
|
||||
- [ ] Test basic API endpoints (`/health`, `/system/status`)
|
||||
- [ ] Understand video file naming conventions
|
||||
- [ ] Plan error handling strategy
|
||||
|
||||
### Video Selection
|
||||
- [ ] Implement video listing with appropriate filters
|
||||
- [ ] Add video validation before processing
|
||||
- [ ] Handle pagination for large video collections
|
||||
- [ ] Implement caching for video metadata
|
||||
|
||||
### Video Playback
|
||||
- [ ] Test video streaming with range requests
|
||||
- [ ] Implement thumbnail generation for previews
|
||||
- [ ] Add progress tracking for video playback
|
||||
- [ ] Handle different video formats (MP4, AVI)
|
||||
|
||||
### Error Handling
|
||||
- [ ] Handle network connectivity issues
|
||||
- [ ] Manage video not found scenarios
|
||||
- [ ] Deal with invalid range requests
|
||||
- [ ] Implement retry logic for transient failures
|
||||
|
||||
### Performance
|
||||
- [ ] Use range requests for efficient seeking
|
||||
- [ ] Implement client-side caching where appropriate
|
||||
- [ ] Monitor bandwidth usage for video streaming
|
||||
- [ ] Consider thumbnail caching for better UX
|
||||
|
||||
## 🎯 Next Steps
|
||||
|
||||
1. **Test Integration**: Use the provided examples to test basic connectivity
|
||||
2. **Implement Error Handling**: Add robust error handling for production use
|
||||
3. **Optimize Performance**: Implement caching and efficient streaming
|
||||
4. **Monitor Usage**: Track API usage and performance metrics
|
||||
5. **Security Review**: Consider authentication if exposing externally
|
||||
|
||||
This guide provides everything needed for successful integration with the USDA Vision Camera System's video streaming functionality. The system is designed to be simple and reliable for AI agents and external systems to consume video content efficiently.
|
||||
207
camera-management-api/docs/API_CHANGES_SUMMARY.md
Normal file
207
camera-management-api/docs/API_CHANGES_SUMMARY.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# API Changes Summary: Camera Settings and Video Format Updates
|
||||
|
||||
## Overview
|
||||
This document tracks major API changes including camera settings enhancements and the MP4 video format update.
|
||||
|
||||
## 🎥 Latest Update: MP4 Video Format (v2.1)
|
||||
**Date**: August 2025
|
||||
|
||||
**Major Changes**:
|
||||
- **Video Format**: Changed from AVI/XVID to MP4/MPEG-4 format
|
||||
- **File Extensions**: New recordings use `.mp4` instead of `.avi`
|
||||
- **File Size**: ~40% reduction in file sizes
|
||||
- **Streaming**: Better web browser compatibility
|
||||
|
||||
**New Configuration Fields**:
|
||||
```json
|
||||
{
|
||||
"video_format": "mp4", // File format: "mp4" or "avi"
|
||||
"video_codec": "mp4v", // Video codec: "mp4v", "XVID", "MJPG"
|
||||
"video_quality": 95 // Quality: 0-100 (higher = better)
|
||||
}
|
||||
```
|
||||
|
||||
**Frontend Impact**:
|
||||
- ✅ Better streaming performance and browser support
|
||||
- ✅ Smaller file sizes for faster transfers
|
||||
- ✅ Universal HTML5 video player compatibility
|
||||
- ✅ Backward compatible with existing AVI files
|
||||
|
||||
**Documentation**: See [MP4 Format Update Guide](MP4_FORMAT_UPDATE.md)
|
||||
|
||||
---
|
||||
|
||||
## Previous Changes: Camera Settings and Filename Handling
|
||||
|
||||
Enhanced the `POST /cameras/{camera_name}/start-recording` API endpoint to accept optional camera settings (shutter speed/exposure, gain, and fps) and ensure all filenames have datetime prefixes.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. API Models (`usda_vision_system/api/models.py`)
|
||||
- **Enhanced `StartRecordingRequest`** to include optional parameters:
|
||||
- `exposure_ms: Optional[float]` - Exposure time in milliseconds
|
||||
- `gain: Optional[float]` - Camera gain value
|
||||
- `fps: Optional[float]` - Target frames per second
|
||||
|
||||
### 2. Camera Recorder (`usda_vision_system/camera/recorder.py`)
|
||||
- **Added `update_camera_settings()` method** to dynamically update camera settings:
|
||||
- Updates exposure time using `mvsdk.CameraSetExposureTime()`
|
||||
- Updates gain using `mvsdk.CameraSetAnalogGain()`
|
||||
- Updates target FPS in camera configuration
|
||||
- Logs all setting changes
|
||||
- Returns boolean indicating success/failure
|
||||
|
||||
### 3. Camera Manager (`usda_vision_system/camera/manager.py`)
|
||||
- **Enhanced `manual_start_recording()` method** to accept new parameters:
|
||||
- Added optional `exposure_ms`, `gain`, and `fps` parameters
|
||||
- Calls `update_camera_settings()` if any settings are provided
|
||||
- **Automatic datetime prefix**: Always prepends timestamp to filename
|
||||
- If custom filename provided: `{timestamp}_{custom_filename}`
|
||||
- If no filename provided: `{camera_name}_manual_{timestamp}.avi`
|
||||
|
||||
### 4. API Server (`usda_vision_system/api/server.py`)
|
||||
- **Updated start-recording endpoint** to:
|
||||
- Pass new camera settings to camera manager
|
||||
- Handle filename response with datetime prefix
|
||||
- Maintain backward compatibility with existing requests
|
||||
|
||||
### 5. API Tests (`api-tests.http`)
|
||||
- **Added comprehensive test examples**:
|
||||
- Basic recording (existing functionality)
|
||||
- Recording with camera settings
|
||||
- Recording with settings only (no filename)
|
||||
- Different parameter combinations
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Recording (unchanged)
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"filename": "test.avi"
|
||||
}
|
||||
```
|
||||
**Result**: File saved as `20241223_143022_test.avi`
|
||||
|
||||
### Recording with Camera Settings
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"filename": "high_quality.avi",
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"fps": 5.0
|
||||
}
|
||||
```
|
||||
**Result**:
|
||||
- Camera settings updated before recording
|
||||
- File saved as `20241223_143022_high_quality.avi`
|
||||
|
||||
### Maximum FPS Recording
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"filename": "max_speed.avi",
|
||||
"exposure_ms": 0.1,
|
||||
"gain": 1.0,
|
||||
"fps": 0
|
||||
}
|
||||
```
|
||||
**Result**:
|
||||
- Camera captures at maximum possible speed (no delay between frames)
|
||||
- Video file saved with 30 FPS metadata for proper playback
|
||||
- Actual capture rate depends on camera hardware and exposure settings
|
||||
|
||||
### Settings Only (no filename)
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"exposure_ms": 1.5,
|
||||
"gain": 3.0,
|
||||
"fps": 7.0
|
||||
}
|
||||
```
|
||||
**Result**:
|
||||
- Camera settings updated
|
||||
- File saved as `camera1_manual_20241223_143022.avi`
|
||||
|
||||
## Key Features
|
||||
|
||||
### 1. **Backward Compatibility**
|
||||
- All existing API calls continue to work unchanged
|
||||
- New parameters are optional
|
||||
- Default behavior preserved when no settings provided
|
||||
|
||||
### 2. **Automatic Datetime Prefix**
|
||||
- **ALL filenames now have datetime prefix** regardless of what's sent
|
||||
- Format: `YYYYMMDD_HHMMSS_` (Atlanta timezone)
|
||||
- Ensures unique filenames and chronological ordering
|
||||
|
||||
### 3. **Dynamic Camera Settings**
|
||||
- Settings can be changed per recording without restarting system
|
||||
- Based on proven implementation from `old tests/camera_video_recorder.py`
|
||||
- Proper error handling and logging
|
||||
|
||||
### 4. **Maximum FPS Capture**
|
||||
- **`fps: 0`** = Capture at maximum possible speed (no delay between frames)
|
||||
- **`fps > 0`** = Capture at specified frame rate with controlled timing
|
||||
- **`fps` omitted** = Uses camera config default (usually 3.0 fps)
|
||||
- Video files saved with 30 FPS metadata when fps=0 for proper playback
|
||||
|
||||
### 5. **Parameter Validation**
|
||||
- Uses Pydantic models for automatic validation
|
||||
- Optional parameters with proper type checking
|
||||
- Descriptive field documentation
|
||||
|
||||
## Testing
|
||||
|
||||
Run the test script to verify functionality:
|
||||
```bash
|
||||
# Start the system first
|
||||
python main.py
|
||||
|
||||
# In another terminal, run tests
|
||||
python test_api_changes.py
|
||||
```
|
||||
|
||||
The test script verifies:
|
||||
- Basic recording functionality
|
||||
- Camera settings application
|
||||
- Filename datetime prefix handling
|
||||
- API response accuracy
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Camera Settings Mapping
|
||||
- **Exposure**: Converted from milliseconds to microseconds for SDK
|
||||
- **Gain**: Converted to camera units (multiplied by 100)
|
||||
- **FPS**: Stored in camera config, used by recording loop
|
||||
|
||||
### Error Handling
|
||||
- Settings update failures are logged but don't prevent recording
|
||||
- Invalid camera names return appropriate HTTP errors
|
||||
- Camera initialization failures are handled gracefully
|
||||
|
||||
### Filename Generation
|
||||
- Uses `format_filename_timestamp()` from timezone utilities
|
||||
- Ensures Atlanta timezone consistency
|
||||
- Handles both custom and auto-generated filenames
|
||||
|
||||
## Similar to Old Implementation
|
||||
The camera settings functionality mirrors the proven approach in `old tests/camera_video_recorder.py`:
|
||||
- Same parameter names and ranges
|
||||
- Same SDK function calls
|
||||
- Same conversion factors
|
||||
- Proven to work with the camera hardware
|
||||
824
camera-management-api/docs/API_DOCUMENTATION.md
Normal file
824
camera-management-api/docs/API_DOCUMENTATION.md
Normal file
@@ -0,0 +1,824 @@
|
||||
# 🚀 USDA Vision Camera System - Complete API Documentation
|
||||
|
||||
This document provides comprehensive documentation for all API endpoints in the USDA Vision Camera System, including recent enhancements and new features.
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
- [🔧 System Status & Health](#-system-status--health)
|
||||
- [📷 Camera Management](#-camera-management)
|
||||
- [🎥 Recording Control](#-recording-control)
|
||||
- [🤖 Auto-Recording Management](#-auto-recording-management)
|
||||
- [🎛️ Camera Configuration](#️-camera-configuration)
|
||||
- [📡 MQTT & Machine Status](#-mqtt--machine-status)
|
||||
- [💾 Storage & File Management](#-storage--file-management)
|
||||
- [🔄 Camera Recovery & Diagnostics](#-camera-recovery--diagnostics)
|
||||
- [📺 Live Streaming](#-live-streaming)
|
||||
- [🎬 Video Streaming & Playback](#-video-streaming--playback)
|
||||
- [🌐 WebSocket Real-time Updates](#-websocket-real-time-updates)
|
||||
|
||||
## 🔧 System Status & Health
|
||||
|
||||
### Get System Status
|
||||
```http
|
||||
GET /system/status
|
||||
```
|
||||
**Response**: `SystemStatusResponse`
|
||||
```json
|
||||
{
|
||||
"system_started": true,
|
||||
"mqtt_connected": true,
|
||||
"last_mqtt_message": "2024-01-15T10:30:00Z",
|
||||
"machines": {
|
||||
"vibratory_conveyor": {
|
||||
"name": "vibratory_conveyor",
|
||||
"state": "ON",
|
||||
"last_updated": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
},
|
||||
"cameras": {
|
||||
"camera1": {
|
||||
"name": "camera1",
|
||||
"status": "ACTIVE",
|
||||
"is_recording": false,
|
||||
"auto_recording_enabled": true
|
||||
}
|
||||
},
|
||||
"active_recordings": 0,
|
||||
"total_recordings": 15,
|
||||
"uptime_seconds": 3600.5
|
||||
}
|
||||
```
|
||||
|
||||
### Health Check
|
||||
```http
|
||||
GET /health
|
||||
```
|
||||
**Response**: Simple health status
|
||||
```json
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 📷 Camera Management
|
||||
|
||||
### Get All Cameras
|
||||
```http
|
||||
GET /cameras
|
||||
```
|
||||
**Response**: `Dict[str, CameraStatusResponse]`
|
||||
|
||||
### Get Specific Camera Status
|
||||
```http
|
||||
GET /cameras/{camera_name}/status
|
||||
```
|
||||
**Response**: `CameraStatusResponse`
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"status": "ACTIVE",
|
||||
"is_recording": false,
|
||||
"last_checked": "2024-01-15T10:30:00Z",
|
||||
"last_error": null,
|
||||
"device_info": {
|
||||
"model": "GigE Camera",
|
||||
"serial": "12345"
|
||||
},
|
||||
"current_recording_file": null,
|
||||
"recording_start_time": null,
|
||||
"auto_recording_enabled": true,
|
||||
"auto_recording_active": false,
|
||||
"auto_recording_failure_count": 0,
|
||||
"auto_recording_last_attempt": null,
|
||||
"auto_recording_last_error": null
|
||||
}
|
||||
```
|
||||
|
||||
## 🎥 Recording Control
|
||||
|
||||
### Start Recording
|
||||
```http
|
||||
POST /cameras/{camera_name}/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "test_recording.avi",
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"fps": 5.0
|
||||
}
|
||||
```
|
||||
|
||||
**Request Model**: `StartRecordingRequest`
|
||||
- `filename` (optional): Custom filename (datetime prefix will be added automatically)
|
||||
- `exposure_ms` (optional): Exposure time in milliseconds
|
||||
- `gain` (optional): Camera gain value
|
||||
- `fps` (optional): Target frames per second
|
||||
|
||||
**Response**: `StartRecordingResponse`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Recording started for camera1",
|
||||
"filename": "20240115_103000_test_recording.avi"
|
||||
}
|
||||
```
|
||||
|
||||
**Key Features**:
|
||||
- ✅ **Automatic datetime prefix**: All filenames get `YYYYMMDD_HHMMSS_` prefix
|
||||
- ✅ **Dynamic camera settings**: Adjust exposure, gain, and FPS per recording
|
||||
- ✅ **Backward compatibility**: All existing API calls work unchanged
|
||||
|
||||
### Stop Recording
|
||||
```http
|
||||
POST /cameras/{camera_name}/stop-recording
|
||||
```
|
||||
**Response**: `StopRecordingResponse`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Recording stopped for camera1",
|
||||
"duration_seconds": 45.2
|
||||
}
|
||||
```
|
||||
|
||||
## 🤖 Auto-Recording Management
|
||||
|
||||
### Enable Auto-Recording for Camera
|
||||
```http
|
||||
POST /cameras/{camera_name}/auto-recording/enable
|
||||
```
|
||||
**Response**: `AutoRecordingConfigResponse`
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Auto-recording enabled for camera1",
|
||||
"camera_name": "camera1",
|
||||
"enabled": true
|
||||
}
|
||||
```
|
||||
|
||||
### Disable Auto-Recording for Camera
|
||||
```http
|
||||
POST /cameras/{camera_name}/auto-recording/disable
|
||||
```
|
||||
**Response**: `AutoRecordingConfigResponse`
|
||||
|
||||
### Get Auto-Recording Status
|
||||
```http
|
||||
GET /auto-recording/status
|
||||
```
|
||||
**Response**: `AutoRecordingStatusResponse`
|
||||
```json
|
||||
{
|
||||
"running": true,
|
||||
"auto_recording_enabled": true,
|
||||
"retry_queue": {},
|
||||
"enabled_cameras": ["camera1", "camera2"]
|
||||
}
|
||||
```
|
||||
|
||||
**Auto-Recording Features**:
|
||||
- 🤖 **MQTT-triggered recording**: Automatically starts/stops based on machine state
|
||||
- 🔄 **Retry logic**: Failed recordings are retried with configurable delays
|
||||
- 📊 **Per-camera control**: Enable/disable auto-recording individually
|
||||
- 📈 **Status tracking**: Monitor failure counts and last attempts
|
||||
|
||||
## 🎛️ Camera Configuration
|
||||
|
||||
### Get Camera Configuration
|
||||
```http
|
||||
GET /cameras/{camera_name}/config
|
||||
```
|
||||
**Response**: `CameraConfigResponse`
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "blower_separator",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 0.3,
|
||||
"gain": 4.0,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"video_format": "mp4",
|
||||
"video_codec": "mp4v",
|
||||
"video_quality": 95,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
"contrast": 100,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 0,
|
||||
"wb_red_gain": 0.94,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.87,
|
||||
"anti_flicker_enabled": false,
|
||||
"light_frequency": 0,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 2
|
||||
}
|
||||
```
|
||||
|
||||
### Update Camera Configuration
|
||||
```http
|
||||
PUT /cameras/{camera_name}/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"target_fps": 5.0,
|
||||
"sharpness": 130
|
||||
}
|
||||
```
|
||||
|
||||
### Apply Configuration (Restart Required)
|
||||
```http
|
||||
POST /cameras/{camera_name}/apply-config
|
||||
```
|
||||
|
||||
**Configuration Categories**:
|
||||
- ✅ **Real-time**: `exposure_ms`, `gain`, `target_fps`, `sharpness`, `contrast`, etc.
|
||||
- ⚠️ **Restart required**: `noise_filter_enabled`, `denoise_3d_enabled`, `bit_depth`, `video_format`, `video_codec`, `video_quality`
|
||||
|
||||
For detailed configuration options, see [Camera Configuration API Guide](api/CAMERA_CONFIG_API.md).
|
||||
|
||||
## 📡 MQTT & Machine Status
|
||||
|
||||
### Get All Machines
|
||||
```http
|
||||
GET /machines
|
||||
```
|
||||
**Response**: `Dict[str, MachineStatusResponse]`
|
||||
|
||||
### Get MQTT Status
|
||||
```http
|
||||
GET /mqtt/status
|
||||
```
|
||||
**Response**: `MQTTStatusResponse`
|
||||
```json
|
||||
{
|
||||
"connected": true,
|
||||
"broker_host": "192.168.1.110",
|
||||
"broker_port": 1883,
|
||||
"subscribed_topics": ["vibratory_conveyor", "blower_separator"],
|
||||
"last_message_time": "2024-01-15T10:30:00Z",
|
||||
"message_count": 1250,
|
||||
"error_count": 2,
|
||||
"uptime_seconds": 3600.5
|
||||
}
|
||||
```
|
||||
|
||||
### Get MQTT Events History
|
||||
```http
|
||||
GET /mqtt/events?limit=10
|
||||
```
|
||||
**Response**: `MQTTEventsHistoryResponse`
|
||||
```json
|
||||
{
|
||||
"events": [
|
||||
{
|
||||
"machine_name": "vibratory_conveyor",
|
||||
"topic": "vibratory_conveyor",
|
||||
"payload": "ON",
|
||||
"normalized_state": "ON",
|
||||
"timestamp": "2024-01-15T10:30:00Z",
|
||||
"message_number": 1250
|
||||
}
|
||||
],
|
||||
"total_events": 1250,
|
||||
"last_updated": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 💾 Storage & File Management
|
||||
|
||||
### Get Storage Statistics
|
||||
```http
|
||||
GET /storage/stats
|
||||
```
|
||||
**Response**: `StorageStatsResponse`
|
||||
```json
|
||||
{
|
||||
"base_path": "/storage",
|
||||
"total_files": 150,
|
||||
"total_size_bytes": 5368709120,
|
||||
"cameras": {
|
||||
"camera1": {
|
||||
"file_count": 75,
|
||||
"total_size_bytes": 2684354560
|
||||
},
|
||||
"camera2": {
|
||||
"file_count": 75,
|
||||
"total_size_bytes": 2684354560
|
||||
}
|
||||
},
|
||||
"disk_usage": {
|
||||
"total_bytes": 107374182400,
|
||||
"used_bytes": 53687091200,
|
||||
"free_bytes": 53687091200,
|
||||
"usage_percent": 50.0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get File List
|
||||
```http
|
||||
POST /storage/files
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"camera_name": "camera1",
|
||||
"start_date": "2024-01-15",
|
||||
"end_date": "2024-01-16",
|
||||
"limit": 50
|
||||
}
|
||||
```
|
||||
**Response**: `FileListResponse`
|
||||
```json
|
||||
{
|
||||
"files": [
|
||||
{
|
||||
"filename": "20240115_103000_test_recording.avi",
|
||||
"camera_name": "camera1",
|
||||
"size_bytes": 52428800,
|
||||
"created_time": "2024-01-15T10:30:00Z",
|
||||
"duration_seconds": 30.5
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Cleanup Old Files
|
||||
```http
|
||||
POST /storage/cleanup
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"max_age_days": 30
|
||||
}
|
||||
```
|
||||
**Response**: `CleanupResponse`
|
||||
```json
|
||||
{
|
||||
"files_removed": 25,
|
||||
"bytes_freed": 1073741824,
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 Camera Recovery & Diagnostics
|
||||
|
||||
### Test Camera Connection
|
||||
```http
|
||||
POST /cameras/{camera_name}/test-connection
|
||||
```
|
||||
**Response**: `CameraTestResponse`
|
||||
|
||||
### Reconnect Camera
|
||||
```http
|
||||
POST /cameras/{camera_name}/reconnect
|
||||
```
|
||||
**Response**: `CameraRecoveryResponse`
|
||||
|
||||
### Restart Camera Grab Process
|
||||
```http
|
||||
POST /cameras/{camera_name}/restart-grab
|
||||
```
|
||||
**Response**: `CameraRecoveryResponse`
|
||||
|
||||
### Reset Camera Timestamp
|
||||
```http
|
||||
POST /cameras/{camera_name}/reset-timestamp
|
||||
```
|
||||
**Response**: `CameraRecoveryResponse`
|
||||
|
||||
### Full Camera Reset
|
||||
```http
|
||||
POST /cameras/{camera_name}/full-reset
|
||||
```
|
||||
**Response**: `CameraRecoveryResponse`
|
||||
|
||||
### Reinitialize Camera
|
||||
```http
|
||||
POST /cameras/{camera_name}/reinitialize
|
||||
```
|
||||
**Response**: `CameraRecoveryResponse`
|
||||
|
||||
**Recovery Response Example**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Camera camera1 reconnected successfully",
|
||||
"camera_name": "camera1",
|
||||
"operation": "reconnect",
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 📺 Live Streaming
|
||||
|
||||
### Get Live MJPEG Stream
|
||||
```http
|
||||
GET /cameras/{camera_name}/stream
|
||||
```
|
||||
**Response**: MJPEG video stream (multipart/x-mixed-replace)
|
||||
|
||||
### Start Camera Stream
|
||||
```http
|
||||
POST /cameras/{camera_name}/start-stream
|
||||
```
|
||||
|
||||
### Stop Camera Stream
|
||||
```http
|
||||
POST /cameras/{camera_name}/stop-stream
|
||||
```
|
||||
|
||||
**Streaming Features**:
|
||||
- 📺 **MJPEG format**: Compatible with web browsers and React apps
|
||||
- 🔄 **Concurrent operation**: Stream while recording simultaneously
|
||||
- ⚡ **Low latency**: Real-time preview for monitoring
|
||||
|
||||
For detailed streaming integration, see [Streaming Guide](guides/STREAMING_GUIDE.md).
|
||||
|
||||
## 🎬 Video Streaming & Playback
|
||||
|
||||
The system includes a comprehensive video streaming module that provides YouTube-like video playback capabilities with HTTP range request support, thumbnail generation, and intelligent caching.
|
||||
|
||||
### List Videos
|
||||
```http
|
||||
GET /videos/
|
||||
```
|
||||
**Query Parameters:**
|
||||
- `camera_name` (optional): Filter by camera name
|
||||
- `start_date` (optional): Filter videos created after this date (ISO format)
|
||||
- `end_date` (optional): Filter videos created before this date (ISO format)
|
||||
- `limit` (optional): Maximum number of results (default: 50, max: 1000)
|
||||
- `include_metadata` (optional): Include video metadata (default: false)
|
||||
|
||||
**Response**: `VideoListResponse`
|
||||
```json
|
||||
{
|
||||
"videos": [
|
||||
{
|
||||
"file_id": "camera1_auto_blower_separator_20250804_143022.mp4",
|
||||
"camera_name": "camera1",
|
||||
"filename": "camera1_auto_blower_separator_20250804_143022.mp4",
|
||||
"file_size_bytes": 31457280,
|
||||
"format": "mp4",
|
||||
"status": "completed",
|
||||
"created_at": "2025-08-04T14:30:22",
|
||||
"start_time": "2025-08-04T14:30:22",
|
||||
"end_time": "2025-08-04T14:32:22",
|
||||
"machine_trigger": "blower_separator",
|
||||
"is_streamable": true,
|
||||
"needs_conversion": false,
|
||||
"metadata": {
|
||||
"duration_seconds": 120.5,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"fps": 30.0,
|
||||
"codec": "mp4v",
|
||||
"bitrate": 5000000,
|
||||
"aspect_ratio": 1.777
|
||||
}
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Get Video Information
|
||||
```http
|
||||
GET /videos/{file_id}
|
||||
```
|
||||
**Response**: `VideoInfoResponse` with detailed video information including metadata.
|
||||
|
||||
### Stream Video
|
||||
```http
|
||||
GET /videos/{file_id}/stream
|
||||
```
|
||||
**Headers:**
|
||||
- `Range: bytes=0-1023` (optional): Request specific byte range for seeking
|
||||
|
||||
**Features:**
|
||||
- ✅ **HTTP Range Requests**: Enables video seeking and progressive download
|
||||
- ✅ **Partial Content**: Returns 206 status for range requests
|
||||
- ✅ **Format Conversion**: Automatic AVI to MP4 conversion for web compatibility
|
||||
- ✅ **Intelligent Caching**: Optimized performance with byte-range caching
|
||||
- ✅ **CORS Enabled**: Ready for web browser integration
|
||||
|
||||
**Response Headers:**
|
||||
- `Accept-Ranges: bytes`
|
||||
- `Content-Length: {size}`
|
||||
- `Content-Range: bytes {start}-{end}/{total}` (for range requests)
|
||||
- `Cache-Control: public, max-age=3600`
|
||||
|
||||
### Get Video Thumbnail
|
||||
```http
|
||||
GET /videos/{file_id}/thumbnail?timestamp=5.0&width=320&height=240
|
||||
```
|
||||
**Query Parameters:**
|
||||
- `timestamp` (optional): Time position in seconds (default: 1.0)
|
||||
- `width` (optional): Thumbnail width in pixels (default: 320)
|
||||
- `height` (optional): Thumbnail height in pixels (default: 240)
|
||||
|
||||
**Response**: JPEG image data with caching headers
|
||||
|
||||
### Get Streaming Information
|
||||
```http
|
||||
GET /videos/{file_id}/info
|
||||
```
|
||||
**Response**: `StreamingInfoResponse`
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"file_size_bytes": 52428800,
|
||||
"content_type": "video/mp4",
|
||||
"supports_range_requests": true,
|
||||
"chunk_size_bytes": 262144
|
||||
}
|
||||
```
|
||||
|
||||
### Video Validation
|
||||
```http
|
||||
POST /videos/{file_id}/validate
|
||||
```
|
||||
**Response**: Validation status and accessibility check
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"is_valid": true
|
||||
}
|
||||
```
|
||||
|
||||
### Cache Management
|
||||
```http
|
||||
POST /videos/{file_id}/cache/invalidate
|
||||
```
|
||||
**Response**: Cache invalidation status
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"cache_invalidated": true
|
||||
}
|
||||
```
|
||||
|
||||
### Admin: Cache Cleanup
|
||||
```http
|
||||
POST /admin/videos/cache/cleanup?max_size_mb=100
|
||||
```
|
||||
**Response**: Cache cleanup results
|
||||
```json
|
||||
{
|
||||
"cache_cleaned": true,
|
||||
"entries_removed": 15,
|
||||
"max_size_mb": 100
|
||||
}
|
||||
```
|
||||
|
||||
**Video Streaming Features**:
|
||||
- 🎥 **Multiple Formats**: Native MP4 support with AVI conversion
|
||||
- 📱 **Web Compatible**: Direct integration with HTML5 video elements
|
||||
- ⚡ **High Performance**: Intelligent caching and adaptive chunking
|
||||
- 🖼️ **Thumbnail Generation**: Extract preview images at any timestamp
|
||||
- 🔄 **Range Requests**: Efficient seeking and progressive download
|
||||
|
||||
## 🌐 WebSocket Real-time Updates
|
||||
|
||||
### Connect to WebSocket
|
||||
```javascript
|
||||
const ws = new WebSocket('ws://localhost:8000/ws');
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const update = JSON.parse(event.data);
|
||||
console.log('Real-time update:', update);
|
||||
};
|
||||
```
|
||||
|
||||
**WebSocket Message Types**:
|
||||
- `system_status`: System status changes
|
||||
- `camera_status`: Camera status updates
|
||||
- `recording_started`: Recording start events
|
||||
- `recording_stopped`: Recording stop events
|
||||
- `mqtt_message`: MQTT message received
|
||||
- `auto_recording_event`: Auto-recording status changes
|
||||
|
||||
**Example WebSocket Message**:
|
||||
```json
|
||||
{
|
||||
"type": "recording_started",
|
||||
"data": {
|
||||
"camera_name": "camera1",
|
||||
"filename": "20240115_103000_auto_recording.avi",
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
},
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 Quick Start Examples
|
||||
|
||||
### Basic System Monitoring
|
||||
```bash
|
||||
# Check system health
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Get overall system status
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# Get all camera statuses
|
||||
curl http://localhost:8000/cameras
|
||||
```
|
||||
|
||||
### Manual Recording Control
|
||||
```bash
|
||||
# Start recording with default settings
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"filename": "manual_test.avi"}'
|
||||
|
||||
# Start recording with custom camera settings
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filename": "high_quality.avi",
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"fps": 5.0
|
||||
}'
|
||||
|
||||
# Stop recording
|
||||
curl -X POST http://localhost:8000/cameras/camera1/stop-recording
|
||||
```
|
||||
|
||||
### Auto-Recording Management
|
||||
```bash
|
||||
# Enable auto-recording for camera1
|
||||
curl -X POST http://localhost:8000/cameras/camera1/auto-recording/enable
|
||||
|
||||
# Check auto-recording status
|
||||
curl http://localhost:8000/auto-recording/status
|
||||
|
||||
# Disable auto-recording for camera1
|
||||
curl -X POST http://localhost:8000/cameras/camera1/auto-recording/disable
|
||||
```
|
||||
|
||||
### Video Streaming Operations
|
||||
```bash
|
||||
# List all videos
|
||||
curl http://localhost:8000/videos/
|
||||
|
||||
# List videos from specific camera with metadata
|
||||
curl "http://localhost:8000/videos/?camera_name=camera1&include_metadata=true"
|
||||
|
||||
# Get video information
|
||||
curl http://localhost:8000/videos/camera1_recording_20250804_143022.avi
|
||||
|
||||
# Get video thumbnail
|
||||
curl "http://localhost:8000/videos/camera1_recording_20250804_143022.avi/thumbnail?timestamp=5.0&width=320&height=240" \
|
||||
--output thumbnail.jpg
|
||||
|
||||
# Get streaming info
|
||||
curl http://localhost:8000/videos/camera1_recording_20250804_143022.avi/info
|
||||
|
||||
# Stream video with range request
|
||||
curl -H "Range: bytes=0-1023" \
|
||||
http://localhost:8000/videos/camera1_recording_20250804_143022.avi/stream
|
||||
|
||||
# Validate video file
|
||||
curl -X POST http://localhost:8000/videos/camera1_recording_20250804_143022.avi/validate
|
||||
|
||||
# Clean up video cache (admin)
|
||||
curl -X POST "http://localhost:8000/admin/videos/cache/cleanup?max_size_mb=100"
|
||||
```
|
||||
|
||||
### Camera Configuration
|
||||
```bash
|
||||
# Get current camera configuration
|
||||
curl http://localhost:8000/cameras/camera1/config
|
||||
|
||||
# Update camera settings (real-time)
|
||||
curl -X PUT http://localhost:8000/cameras/camera1/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"exposure_ms": 1.5,
|
||||
"gain": 3.0,
|
||||
"sharpness": 130,
|
||||
"contrast": 120
|
||||
}'
|
||||
```
|
||||
|
||||
## 📈 Recent API Changes & Enhancements
|
||||
|
||||
### ✨ New in Latest Version
|
||||
|
||||
#### 1. Enhanced Recording API
|
||||
- **Dynamic camera settings**: Set exposure, gain, and FPS per recording
|
||||
- **Automatic datetime prefixes**: All filenames get timestamp prefixes
|
||||
- **Backward compatibility**: Existing API calls work unchanged
|
||||
|
||||
#### 2. Auto-Recording Feature
|
||||
- **Per-camera control**: Enable/disable auto-recording individually
|
||||
- **MQTT integration**: Automatic recording based on machine states
|
||||
- **Retry logic**: Failed recordings are automatically retried
|
||||
- **Status tracking**: Monitor auto-recording attempts and failures
|
||||
|
||||
#### 3. Advanced Camera Configuration
|
||||
- **Real-time settings**: Update exposure, gain, image quality without restart
|
||||
- **Image enhancement**: Sharpness, contrast, saturation, gamma controls
|
||||
- **Noise reduction**: Configurable noise filtering and 3D denoising
|
||||
- **HDR support**: High Dynamic Range imaging capabilities
|
||||
|
||||
#### 4. Live Streaming
|
||||
- **MJPEG streaming**: Real-time camera preview
|
||||
- **Concurrent operation**: Stream while recording simultaneously
|
||||
- **Web-compatible**: Direct integration with React/HTML video elements
|
||||
|
||||
#### 5. Enhanced Monitoring
|
||||
- **MQTT event history**: Track machine state changes over time
|
||||
- **Storage statistics**: Monitor disk usage and file counts
|
||||
- **WebSocket updates**: Real-time system status notifications
|
||||
|
||||
#### 6. Video Streaming Module
|
||||
- **HTTP Range Requests**: Efficient video seeking and progressive download
|
||||
- **Thumbnail Generation**: Extract preview images from videos at any timestamp
|
||||
- **Format Conversion**: Automatic AVI to MP4 conversion for web compatibility
|
||||
- **Intelligent Caching**: Byte-range caching for optimal streaming performance
|
||||
- **Admin Tools**: Cache management and video validation endpoints
|
||||
|
||||
### 🔄 Migration Notes
|
||||
|
||||
#### From Previous Versions
|
||||
1. **Recording API**: All existing calls work, but now return filenames with datetime prefixes
|
||||
2. **Configuration**: New camera settings are optional and backward compatible
|
||||
3. **Auto-recording**: New feature, requires enabling in `config.json` and per camera
|
||||
|
||||
#### Configuration Updates
|
||||
```json
|
||||
{
|
||||
"cameras": [
|
||||
{
|
||||
"name": "camera1",
|
||||
"auto_start_recording_enabled": true, // NEW: Enable auto-recording
|
||||
"sharpness": 120, // NEW: Image quality settings
|
||||
"contrast": 110,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": true,
|
||||
"hdr_enabled": false
|
||||
}
|
||||
],
|
||||
"system": {
|
||||
"auto_recording_enabled": true // NEW: Global auto-recording toggle
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔗 Related Documentation
|
||||
|
||||
- [📷 Camera Configuration API Guide](api/CAMERA_CONFIG_API.md) - Detailed camera settings
|
||||
- [🤖 Auto-Recording Feature Guide](features/AUTO_RECORDING_FEATURE_GUIDE.md) - React integration
|
||||
- [📺 Streaming Guide](guides/STREAMING_GUIDE.md) - Live video streaming
|
||||
- [🎬 Video Streaming Guide](VIDEO_STREAMING.md) - Video playback and streaming
|
||||
- [🤖 AI Agent Video Integration Guide](AI_AGENT_VIDEO_INTEGRATION_GUIDE.md) - Complete integration guide for AI agents
|
||||
- [🔧 Camera Recovery Guide](guides/CAMERA_RECOVERY_GUIDE.md) - Troubleshooting
|
||||
- [📡 MQTT Logging Guide](guides/MQTT_LOGGING_GUIDE.md) - MQTT configuration
|
||||
|
||||
## 📞 Support & Integration
|
||||
|
||||
### API Base URL
|
||||
- **Development**: `http://localhost:8000`
|
||||
- **Production**: Configure in `config.json` under `system.api_host` and `system.api_port`
|
||||
|
||||
### Error Handling
|
||||
All endpoints return standard HTTP status codes:
|
||||
- `200`: Success
|
||||
- `206`: Partial Content (for video range requests)
|
||||
- `400`: Bad Request (invalid parameters)
|
||||
- `404`: Resource not found (camera, file, video, etc.)
|
||||
- `416`: Range Not Satisfiable (invalid video range request)
|
||||
- `500`: Internal server error
|
||||
- `503`: Service unavailable (camera manager, MQTT, etc.)
|
||||
|
||||
**Video Streaming Specific Errors:**
|
||||
- `404`: Video file not found or not streamable
|
||||
- `416`: Invalid range request (malformed Range header)
|
||||
- `500`: Failed to read video data or generate thumbnail
|
||||
|
||||
### Rate Limiting
|
||||
- No rate limiting currently implemented
|
||||
- WebSocket connections are limited to reasonable concurrent connections
|
||||
|
||||
### CORS Support
|
||||
- CORS is enabled for web dashboard integration
|
||||
- Configure allowed origins in the API server settings
|
||||
```
|
||||
```
|
||||
195
camera-management-api/docs/API_QUICK_REFERENCE.md
Normal file
195
camera-management-api/docs/API_QUICK_REFERENCE.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# 🚀 USDA Vision Camera System - API Quick Reference
|
||||
|
||||
Quick reference for the most commonly used API endpoints. For complete documentation, see [API_DOCUMENTATION.md](API_DOCUMENTATION.md).
|
||||
|
||||
## 🔧 System Status
|
||||
|
||||
```bash
|
||||
# Health check
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# System overview
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# All cameras
|
||||
curl http://localhost:8000/cameras
|
||||
|
||||
# All machines
|
||||
curl http://localhost:8000/machines
|
||||
```
|
||||
|
||||
## 🎥 Recording Control
|
||||
|
||||
### Start Recording (Basic)
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"filename": "test.avi"}'
|
||||
```
|
||||
|
||||
### Start Recording (With Settings)
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"filename": "high_quality.avi",
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"fps": 5.0
|
||||
}'
|
||||
```
|
||||
|
||||
### Stop Recording
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/cameras/camera1/stop-recording
|
||||
```
|
||||
|
||||
## 🤖 Auto-Recording
|
||||
|
||||
```bash
|
||||
# Enable auto-recording
|
||||
curl -X POST http://localhost:8000/cameras/camera1/auto-recording/enable
|
||||
|
||||
# Disable auto-recording
|
||||
curl -X POST http://localhost:8000/cameras/camera1/auto-recording/disable
|
||||
|
||||
# Check auto-recording status
|
||||
curl http://localhost:8000/auto-recording/status
|
||||
```
|
||||
|
||||
## 🎛️ Camera Configuration
|
||||
|
||||
```bash
|
||||
# Get camera config
|
||||
curl http://localhost:8000/cameras/camera1/config
|
||||
|
||||
# Update camera settings
|
||||
curl -X PUT http://localhost:8000/cameras/camera1/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"exposure_ms": 1.5,
|
||||
"gain": 3.0,
|
||||
"sharpness": 130
|
||||
}'
|
||||
```
|
||||
|
||||
## 📺 Live Streaming
|
||||
|
||||
```bash
|
||||
# Start streaming
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-stream
|
||||
|
||||
# Get MJPEG stream (use in browser/video element)
|
||||
# http://localhost:8000/cameras/camera1/stream
|
||||
|
||||
# Stop streaming
|
||||
curl -X POST http://localhost:8000/cameras/camera1/stop-stream
|
||||
```
|
||||
|
||||
## 🔄 Camera Recovery
|
||||
|
||||
```bash
|
||||
# Test connection
|
||||
curl -X POST http://localhost:8000/cameras/camera1/test-connection
|
||||
|
||||
# Reconnect camera
|
||||
curl -X POST http://localhost:8000/cameras/camera1/reconnect
|
||||
|
||||
# Full reset
|
||||
curl -X POST http://localhost:8000/cameras/camera1/full-reset
|
||||
```
|
||||
|
||||
## 💾 Storage Management
|
||||
|
||||
```bash
|
||||
# Storage statistics
|
||||
curl http://localhost:8000/storage/stats
|
||||
|
||||
# List files
|
||||
curl -X POST http://localhost:8000/storage/files \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"camera_name": "camera1", "limit": 10}'
|
||||
|
||||
# Cleanup old files
|
||||
curl -X POST http://localhost:8000/storage/cleanup \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"max_age_days": 30}'
|
||||
```
|
||||
|
||||
## 📡 MQTT Monitoring
|
||||
|
||||
```bash
|
||||
# MQTT status
|
||||
curl http://localhost:8000/mqtt/status
|
||||
|
||||
# Recent MQTT events
|
||||
curl http://localhost:8000/mqtt/events?limit=10
|
||||
```
|
||||
|
||||
## 🌐 WebSocket Connection
|
||||
|
||||
```javascript
|
||||
// Connect to real-time updates
|
||||
const ws = new WebSocket('ws://localhost:8000/ws');
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const update = JSON.parse(event.data);
|
||||
console.log('Update:', update);
|
||||
};
|
||||
```
|
||||
|
||||
## 📊 Response Examples
|
||||
|
||||
### System Status Response
|
||||
```json
|
||||
{
|
||||
"system_started": true,
|
||||
"mqtt_connected": true,
|
||||
"cameras": {
|
||||
"camera1": {
|
||||
"name": "camera1",
|
||||
"status": "ACTIVE",
|
||||
"is_recording": false,
|
||||
"auto_recording_enabled": true
|
||||
}
|
||||
},
|
||||
"active_recordings": 0,
|
||||
"total_recordings": 15
|
||||
}
|
||||
```
|
||||
|
||||
### Recording Start Response
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Recording started for camera1",
|
||||
"filename": "20240115_103000_test.avi"
|
||||
}
|
||||
```
|
||||
|
||||
### Camera Status Response
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"status": "ACTIVE",
|
||||
"is_recording": false,
|
||||
"auto_recording_enabled": true,
|
||||
"auto_recording_active": false,
|
||||
"auto_recording_failure_count": 0
|
||||
}
|
||||
```
|
||||
|
||||
## 🔗 Related Documentation
|
||||
|
||||
- [📚 Complete API Documentation](API_DOCUMENTATION.md)
|
||||
- [🎛️ Camera Configuration Guide](api/CAMERA_CONFIG_API.md)
|
||||
- [🤖 Auto-Recording Feature Guide](features/AUTO_RECORDING_FEATURE_GUIDE.md)
|
||||
- [📺 Streaming Guide](guides/STREAMING_GUIDE.md)
|
||||
|
||||
## 💡 Tips
|
||||
|
||||
- All filenames automatically get datetime prefixes: `YYYYMMDD_HHMMSS_`
|
||||
- Camera settings can be updated in real-time during recording
|
||||
- Auto-recording is controlled per camera and globally
|
||||
- WebSocket provides real-time updates for dashboard integration
|
||||
- CORS is enabled for web application integration
|
||||
217
camera-management-api/docs/CURRENT_CONFIGURATION.md
Normal file
217
camera-management-api/docs/CURRENT_CONFIGURATION.md
Normal file
@@ -0,0 +1,217 @@
|
||||
# 📋 Current System Configuration Reference
|
||||
|
||||
## Overview
|
||||
This document shows the exact current configuration structure of the USDA Vision Camera System, including all fields and their current values.
|
||||
|
||||
## 🔧 Complete Configuration Structure
|
||||
|
||||
### System Configuration (`config.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"mqtt": {
|
||||
"broker_host": "192.168.1.110",
|
||||
"broker_port": 1883,
|
||||
"username": null,
|
||||
"password": null,
|
||||
"topics": {
|
||||
"vibratory_conveyor": "vision/vibratory_conveyor/state",
|
||||
"blower_separator": "vision/blower_separator/state"
|
||||
}
|
||||
},
|
||||
"storage": {
|
||||
"base_path": "/storage",
|
||||
"max_file_size_mb": 1000,
|
||||
"max_recording_duration_minutes": 60,
|
||||
"cleanup_older_than_days": 30
|
||||
},
|
||||
"system": {
|
||||
"camera_check_interval_seconds": 2,
|
||||
"log_level": "DEBUG",
|
||||
"log_file": "usda_vision_system.log",
|
||||
"api_host": "0.0.0.0",
|
||||
"api_port": 8000,
|
||||
"enable_api": true,
|
||||
"timezone": "America/New_York",
|
||||
"auto_recording_enabled": true
|
||||
},
|
||||
"cameras": [
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "blower_separator",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 0.3,
|
||||
"gain": 4.0,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"video_format": "mp4",
|
||||
"video_codec": "mp4v",
|
||||
"video_quality": 95,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
"sharpness": 0,
|
||||
"contrast": 100,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 0,
|
||||
"wb_red_gain": 0.94,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.87,
|
||||
"anti_flicker_enabled": false,
|
||||
"light_frequency": 0,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 2
|
||||
},
|
||||
{
|
||||
"name": "camera2",
|
||||
"machine_topic": "vibratory_conveyor",
|
||||
"storage_path": "/storage/camera2",
|
||||
"exposure_ms": 0.2,
|
||||
"gain": 2.0,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"video_format": "mp4",
|
||||
"video_codec": "mp4v",
|
||||
"video_quality": 95,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
"sharpness": 0,
|
||||
"contrast": 100,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 0,
|
||||
"wb_red_gain": 1.01,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.87,
|
||||
"anti_flicker_enabled": false,
|
||||
"light_frequency": 0,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Configuration Field Reference
|
||||
|
||||
### MQTT Settings
|
||||
| Field | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| `broker_host` | `"192.168.1.110"` | MQTT broker IP address |
|
||||
| `broker_port` | `1883` | MQTT broker port |
|
||||
| `username` | `null` | MQTT authentication (not used) |
|
||||
| `password` | `null` | MQTT authentication (not used) |
|
||||
|
||||
### MQTT Topics
|
||||
| Machine | Topic | Camera |
|
||||
|---------|-------|--------|
|
||||
| Vibratory Conveyor | `vision/vibratory_conveyor/state` | camera2 |
|
||||
| Blower Separator | `vision/blower_separator/state` | camera1 |
|
||||
|
||||
### Storage Settings
|
||||
| Field | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| `base_path` | `"/storage"` | Root storage directory |
|
||||
| `max_file_size_mb` | `1000` | Maximum file size (1GB) |
|
||||
| `max_recording_duration_minutes` | `60` | Maximum recording duration |
|
||||
| `cleanup_older_than_days` | `30` | Auto-cleanup threshold |
|
||||
|
||||
### System Settings
|
||||
| Field | Value | Description |
|
||||
|-------|-------|-------------|
|
||||
| `camera_check_interval_seconds` | `2` | Camera health check interval |
|
||||
| `log_level` | `"DEBUG"` | Logging verbosity |
|
||||
| `api_host` | `"0.0.0.0"` | API server bind address |
|
||||
| `api_port` | `8000` | API server port |
|
||||
| `timezone` | `"America/New_York"` | System timezone |
|
||||
| `auto_recording_enabled` | `true` | Enable MQTT-triggered recording |
|
||||
|
||||
## 🎥 Camera Configuration Details
|
||||
|
||||
### Camera 1 (Blower Separator)
|
||||
| Setting | Value | Description |
|
||||
|---------|-------|-------------|
|
||||
| **Basic Settings** | | |
|
||||
| `name` | `"camera1"` | Camera identifier |
|
||||
| `machine_topic` | `"blower_separator"` | MQTT topic to monitor |
|
||||
| `storage_path` | `"/storage/camera1"` | Video storage location |
|
||||
| `exposure_ms` | `0.3` | Exposure time (milliseconds) |
|
||||
| `gain` | `4.0` | Camera gain multiplier |
|
||||
| `target_fps` | `0` | Target FPS (0 = unlimited) |
|
||||
| **Video Recording** | | |
|
||||
| `video_format` | `"mp4"` | Video file format |
|
||||
| `video_codec` | `"mp4v"` | Video codec (MPEG-4) |
|
||||
| `video_quality` | `95` | Video quality (0-100) |
|
||||
| **Auto Recording** | | |
|
||||
| `auto_start_recording_enabled` | `true` | Enable auto-recording |
|
||||
| `auto_recording_max_retries` | `3` | Max retry attempts |
|
||||
| `auto_recording_retry_delay_seconds` | `2` | Delay between retries |
|
||||
| **Image Quality** | | |
|
||||
| `sharpness` | `0` | Sharpness adjustment |
|
||||
| `contrast` | `100` | Contrast level |
|
||||
| `saturation` | `100` | Color saturation |
|
||||
| `gamma` | `100` | Gamma correction |
|
||||
| **White Balance** | | |
|
||||
| `auto_white_balance` | `false` | Auto white balance disabled |
|
||||
| `wb_red_gain` | `0.94` | Red channel gain |
|
||||
| `wb_green_gain` | `1.0` | Green channel gain |
|
||||
| `wb_blue_gain` | `0.87` | Blue channel gain |
|
||||
| **Advanced** | | |
|
||||
| `bit_depth` | `8` | Color bit depth |
|
||||
| `hdr_enabled` | `false` | HDR disabled |
|
||||
| `hdr_gain_mode` | `2` | HDR gain mode |
|
||||
|
||||
### Camera 2 (Vibratory Conveyor)
|
||||
| Setting | Value | Difference from Camera 1 |
|
||||
|---------|-------|--------------------------|
|
||||
| `name` | `"camera2"` | Different identifier |
|
||||
| `machine_topic` | `"vibratory_conveyor"` | Different MQTT topic |
|
||||
| `storage_path` | `"/storage/camera2"` | Different storage path |
|
||||
| `exposure_ms` | `0.2` | Faster exposure (0.2 vs 0.3) |
|
||||
| `gain` | `2.0` | Lower gain (2.0 vs 4.0) |
|
||||
| `wb_red_gain` | `1.01` | Different red balance (1.01 vs 0.94) |
|
||||
| `hdr_gain_mode` | `0` | Different HDR mode (0 vs 2) |
|
||||
|
||||
*All other settings are identical to Camera 1*
|
||||
|
||||
## 🔄 Recent Changes
|
||||
|
||||
### MP4 Format Update
|
||||
- **Added**: `video_format`, `video_codec`, `video_quality` fields
|
||||
- **Changed**: Default recording format from AVI to MP4
|
||||
- **Impact**: Requires service restart to take effect
|
||||
|
||||
### Current Status
|
||||
- ✅ Configuration updated with MP4 settings
|
||||
- ⚠️ Service restart required to apply changes
|
||||
- 📁 Existing AVI files remain accessible
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
1. **Target FPS = 0**: Both cameras use unlimited frame rate for maximum capture speed
|
||||
2. **Auto Recording**: Both cameras automatically start recording when their respective machines turn on
|
||||
3. **White Balance**: Manual white balance settings optimized for each camera's environment
|
||||
4. **Storage**: Each camera has its own dedicated storage directory
|
||||
5. **Video Quality**: Set to 95/100 for high-quality recordings with MP4 compression benefits
|
||||
|
||||
## 🔧 Configuration Management
|
||||
|
||||
To modify these settings:
|
||||
1. Edit `config.json` file
|
||||
2. Restart the camera service: `sudo ./start_system.sh`
|
||||
3. Verify changes via API: `GET /cameras/{camera_name}/config`
|
||||
|
||||
For real-time settings (exposure, gain, fps), use the API without restart:
|
||||
```bash
|
||||
PUT /cameras/{camera_name}/config
|
||||
```
|
||||
211
camera-management-api/docs/MP4_FORMAT_UPDATE.md
Normal file
211
camera-management-api/docs/MP4_FORMAT_UPDATE.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# 🎥 MP4 Video Format Update - Frontend Integration Guide
|
||||
|
||||
## Overview
|
||||
The USDA Vision Camera System has been updated to record videos in **MP4 format** instead of AVI format for better streaming compatibility and smaller file sizes.
|
||||
|
||||
## 🔄 What Changed
|
||||
|
||||
### Video Format
|
||||
- **Before**: AVI files with XVID codec (`.avi` extension)
|
||||
- **After**: MP4 files with MPEG-4 codec (`.mp4` extension)
|
||||
|
||||
### File Extensions
|
||||
- All new video recordings now use `.mp4` extension
|
||||
- Existing `.avi` files remain accessible and functional
|
||||
- File size reduction: ~40% smaller than equivalent AVI files
|
||||
|
||||
### API Response Updates
|
||||
New fields added to camera configuration responses:
|
||||
|
||||
```json
|
||||
{
|
||||
"video_format": "mp4", // File format: "mp4" or "avi"
|
||||
"video_codec": "mp4v", // Video codec: "mp4v", "XVID", "MJPG"
|
||||
"video_quality": 95 // Quality: 0-100 (higher = better)
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 Frontend Impact
|
||||
|
||||
### 1. Video Player Compatibility
|
||||
**✅ Better Browser Support**
|
||||
- MP4 format has native support in all modern browsers
|
||||
- No need for additional codecs or plugins
|
||||
- Better mobile device compatibility (iOS/Android)
|
||||
|
||||
### 2. File Handling Updates
|
||||
**File Extension Handling**
|
||||
```javascript
|
||||
// Update file extension checks
|
||||
const isVideoFile = (filename) => {
|
||||
return filename.endsWith('.mp4') || filename.endsWith('.avi');
|
||||
};
|
||||
|
||||
// Video MIME type detection
|
||||
const getVideoMimeType = (filename) => {
|
||||
if (filename.endsWith('.mp4')) return 'video/mp4';
|
||||
if (filename.endsWith('.avi')) return 'video/x-msvideo';
|
||||
return 'video/mp4'; // default
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Video Streaming
|
||||
**Improved Streaming Performance**
|
||||
```javascript
|
||||
// MP4 files can be streamed directly without conversion
|
||||
const videoUrl = `/api/videos/${videoId}/stream`;
|
||||
|
||||
// For HTML5 video element
|
||||
<video controls>
|
||||
<source src={videoUrl} type="video/mp4" />
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
```
|
||||
|
||||
### 4. File Size Display
|
||||
**Updated Size Expectations**
|
||||
- MP4 files are ~40% smaller than equivalent AVI files
|
||||
- Update any file size warnings or storage calculations
|
||||
- Better compression means faster downloads and uploads
|
||||
|
||||
## 📡 API Changes
|
||||
|
||||
### Camera Configuration Endpoint
|
||||
**GET** `/cameras/{camera_name}/config`
|
||||
|
||||
**New Response Fields:**
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "blower_separator",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 0.3,
|
||||
"gain": 4.0,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"video_format": "mp4",
|
||||
"video_codec": "mp4v",
|
||||
"video_quality": 95,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
|
||||
// ... other existing fields
|
||||
}
|
||||
```
|
||||
|
||||
### Video Listing Endpoints
|
||||
**File Extension Updates**
|
||||
- Video files in responses will now have `.mp4` extensions
|
||||
- Existing `.avi` files will still appear in listings
|
||||
- Filter by both extensions when needed
|
||||
|
||||
## 🔧 Configuration Options
|
||||
|
||||
### Video Format Settings
|
||||
```json
|
||||
{
|
||||
"video_format": "mp4", // Options: "mp4", "avi"
|
||||
"video_codec": "mp4v", // Options: "mp4v", "XVID", "MJPG"
|
||||
"video_quality": 95 // Range: 0-100 (higher = better quality)
|
||||
}
|
||||
```
|
||||
|
||||
### Recommended Settings
|
||||
- **Production**: `"mp4"` format, `"mp4v"` codec, `95` quality
|
||||
- **Storage Optimized**: `"mp4"` format, `"mp4v"` codec, `85` quality
|
||||
- **Legacy Mode**: `"avi"` format, `"XVID"` codec, `95` quality
|
||||
|
||||
## 🎯 Frontend Implementation Checklist
|
||||
|
||||
### ✅ Video Player Updates
|
||||
- [ ] Verify HTML5 video player works with MP4 files
|
||||
- [ ] Update video MIME type handling
|
||||
- [ ] Test streaming performance with new format
|
||||
|
||||
### ✅ File Management
|
||||
- [ ] Update file extension filters to include `.mp4`
|
||||
- [ ] Modify file type detection logic
|
||||
- [ ] Update download/upload handling for MP4 files
|
||||
|
||||
### ✅ UI/UX Updates
|
||||
- [ ] Update file size expectations in UI
|
||||
- [ ] Modify any format-specific icons or indicators
|
||||
- [ ] Update help text or tooltips mentioning video formats
|
||||
|
||||
### ✅ Configuration Interface
|
||||
- [ ] Add video format settings to camera config UI
|
||||
- [ ] Include video quality slider/selector
|
||||
- [ ] Add restart warning for video format changes
|
||||
|
||||
### ✅ Testing
|
||||
- [ ] Test video playback with new MP4 files
|
||||
- [ ] Verify backward compatibility with existing AVI files
|
||||
- [ ] Test streaming performance and loading times
|
||||
|
||||
## 🔄 Backward Compatibility
|
||||
|
||||
### Existing AVI Files
|
||||
- All existing `.avi` files remain fully functional
|
||||
- No conversion or migration required
|
||||
- Video player should handle both formats
|
||||
|
||||
### API Compatibility
|
||||
- All existing API endpoints continue to work
|
||||
- New fields are additive (won't break existing code)
|
||||
- Default values provided for new configuration fields
|
||||
|
||||
## 📊 Performance Benefits
|
||||
|
||||
### File Size Reduction
|
||||
```
|
||||
Example 5-minute recording at 1280x1024:
|
||||
- AVI/XVID: ~180 MB
|
||||
- MP4/MPEG-4: ~108 MB (40% reduction)
|
||||
```
|
||||
|
||||
### Streaming Improvements
|
||||
- Faster initial load times
|
||||
- Better progressive download support
|
||||
- Reduced bandwidth usage
|
||||
- Native browser optimization
|
||||
|
||||
### Storage Efficiency
|
||||
- More recordings fit in same storage space
|
||||
- Faster backup and transfer operations
|
||||
- Reduced storage costs over time
|
||||
|
||||
## 🚨 Important Notes
|
||||
|
||||
### Restart Required
|
||||
- Video format changes require camera service restart
|
||||
- Mark video format settings as "restart required" in UI
|
||||
- Provide clear user feedback about restart necessity
|
||||
|
||||
### Browser Compatibility
|
||||
- MP4 format supported in all modern browsers
|
||||
- Better mobile device support than AVI
|
||||
- No additional plugins or codecs needed
|
||||
|
||||
### Quality Assurance
|
||||
- Video quality maintained at 95/100 setting
|
||||
- No visual degradation compared to AVI
|
||||
- High bitrate ensures professional quality
|
||||
|
||||
## 🔗 Related Documentation
|
||||
|
||||
- [API Documentation](API_DOCUMENTATION.md) - Complete API reference
|
||||
- [Camera Configuration API](api/CAMERA_CONFIG_API.md) - Detailed config options
|
||||
- [Video Streaming Guide](VIDEO_STREAMING.md) - Streaming implementation
|
||||
- [MP4 Conversion Summary](../MP4_CONVERSION_SUMMARY.md) - Technical details
|
||||
|
||||
## 📞 Support
|
||||
|
||||
If you encounter any issues with the MP4 format update:
|
||||
|
||||
1. **Video Playback Issues**: Check browser console for codec errors
|
||||
2. **File Size Concerns**: Verify quality settings in camera config
|
||||
3. **Streaming Problems**: Test with both MP4 and AVI files for comparison
|
||||
4. **API Integration**: Refer to updated API documentation
|
||||
|
||||
The MP4 format provides better web compatibility and performance while maintaining the same high video quality required for the USDA vision system.
|
||||
212
camera-management-api/docs/PROJECT_COMPLETE.md
Normal file
212
camera-management-api/docs/PROJECT_COMPLETE.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# 🎉 USDA Vision Camera System - PROJECT COMPLETE!
|
||||
|
||||
## ✅ Final Status: READY FOR PRODUCTION
|
||||
|
||||
The USDA Vision Camera System has been successfully implemented, tested, and documented. All requirements have been met and the system is production-ready.
|
||||
|
||||
## 📋 Completed Requirements
|
||||
|
||||
### ✅ Core Functionality
|
||||
- **MQTT Integration**: Dual topic listening for machine states
|
||||
- **Automatic Recording**: Camera recording triggered by machine on/off states
|
||||
- **GigE Camera Support**: Full integration with camera SDK library
|
||||
- **Multi-threading**: Concurrent MQTT + camera monitoring + recording
|
||||
- **File Management**: Timestamp-based naming in organized directories
|
||||
|
||||
### ✅ Advanced Features
|
||||
- **REST API**: Complete FastAPI server with all endpoints
|
||||
- **WebSocket Support**: Real-time updates for dashboard integration
|
||||
- **Time Synchronization**: Atlanta, Georgia timezone with NTP sync
|
||||
- **Storage Management**: File indexing, cleanup, and statistics
|
||||
- **Comprehensive Logging**: Rotating logs with error tracking
|
||||
- **Configuration System**: JSON-based configuration management
|
||||
|
||||
### ✅ Documentation & Testing
|
||||
- **Complete README**: Installation, usage, API docs, troubleshooting
|
||||
- **Test Suite**: Comprehensive system testing (`test_system.py`)
|
||||
- **Time Verification**: Timezone and sync testing (`check_time.py`)
|
||||
- **Startup Scripts**: Easy deployment with `start_system.sh`
|
||||
- **Clean Repository**: Organized structure with proper .gitignore
|
||||
|
||||
## 🏗️ Final Project Structure
|
||||
|
||||
```
|
||||
USDA-Vision-Cameras/
|
||||
├── README.md # Complete documentation
|
||||
├── main.py # System entry point
|
||||
├── config.json # System configuration
|
||||
├── requirements.txt # Python dependencies
|
||||
├── pyproject.toml # UV package configuration
|
||||
├── .gitignore # Git ignore rules
|
||||
├── start_system.sh # Startup script
|
||||
├── setup_timezone.sh # Time sync setup
|
||||
├── test_system.py # System test suite
|
||||
├── check_time.py # Time verification
|
||||
├── test_timezone.py # Timezone testing
|
||||
├── usda_vision_system/ # Main application
|
||||
│ ├── core/ # Core functionality
|
||||
│ ├── mqtt/ # MQTT integration
|
||||
│ ├── camera/ # Camera management
|
||||
│ ├── storage/ # File management
|
||||
│ ├── api/ # REST API server
|
||||
│ └── main.py # Application coordinator
|
||||
├── camera_sdk/ # GigE camera SDK library
|
||||
├── demos/ # Demo and example code
|
||||
│ ├── cv_grab*.py # Camera SDK usage examples
|
||||
│ └── mqtt_*.py # MQTT demo scripts
|
||||
├── storage/ # Recording storage
|
||||
│ ├── camera1/ # Camera 1 recordings
|
||||
│ └── camera2/ # Camera 2 recordings
|
||||
├── tests/ # Test files and legacy tests
|
||||
├── notebooks/ # Jupyter notebooks
|
||||
└── docs/ # Documentation files
|
||||
```
|
||||
|
||||
## 🚀 How to Deploy
|
||||
|
||||
### 1. Clone and Setup
|
||||
```bash
|
||||
git clone https://github.com/your-username/USDA-Vision-Cameras.git
|
||||
cd USDA-Vision-Cameras
|
||||
uv sync
|
||||
```
|
||||
|
||||
### 2. Configure System
|
||||
```bash
|
||||
# Edit config.json for your environment
|
||||
# Set MQTT broker, camera settings, storage paths
|
||||
```
|
||||
|
||||
### 3. Setup Time Sync
|
||||
```bash
|
||||
./setup_timezone.sh
|
||||
```
|
||||
|
||||
### 4. Test System
|
||||
```bash
|
||||
python test_system.py
|
||||
```
|
||||
|
||||
### 5. Start System
|
||||
```bash
|
||||
./start_system.sh
|
||||
```
|
||||
|
||||
## 🌐 API Integration
|
||||
|
||||
### Dashboard Integration
|
||||
```javascript
|
||||
// React component example
|
||||
const systemStatus = await fetch('http://localhost:8000/system/status');
|
||||
const cameras = await fetch('http://localhost:8000/cameras');
|
||||
|
||||
// WebSocket for real-time updates
|
||||
const ws = new WebSocket('ws://localhost:8000/ws');
|
||||
ws.onmessage = (event) => {
|
||||
const update = JSON.parse(event.data);
|
||||
// Handle real-time system updates
|
||||
};
|
||||
```
|
||||
|
||||
### Manual Control
|
||||
```bash
|
||||
# Start recording manually
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording
|
||||
|
||||
# Stop recording manually
|
||||
curl -X POST http://localhost:8000/cameras/camera1/stop-recording
|
||||
|
||||
# Get system status
|
||||
curl http://localhost:8000/system/status
|
||||
```
|
||||
|
||||
## 📊 System Capabilities
|
||||
|
||||
### Discovered Hardware
|
||||
- **2 GigE Cameras**: Blower-Yield-Cam, Cracker-Cam
|
||||
- **Network Ready**: Cameras accessible at 192.168.1.165, 192.168.1.167
|
||||
- **MQTT Ready**: Configured for broker at 192.168.1.110
|
||||
|
||||
### Recording Features
|
||||
- **Automatic Start/Stop**: Based on MQTT machine states
|
||||
- **Timezone Aware**: Atlanta time timestamps (EST/EDT)
|
||||
- **Organized Storage**: Separate directories per camera
|
||||
- **File Naming**: `camera1_recording_20250725_213000.avi`
|
||||
- **Manual Control**: API endpoints for manual recording
|
||||
|
||||
### Monitoring Features
|
||||
- **Real-time Status**: Camera and machine state monitoring
|
||||
- **Health Checks**: Automatic system health verification
|
||||
- **Performance Tracking**: Recording metrics and system stats
|
||||
- **Error Handling**: Comprehensive error tracking and recovery
|
||||
|
||||
## 🔧 Maintenance
|
||||
|
||||
### Regular Tasks
|
||||
- **Log Monitoring**: Check `usda_vision_system.log`
|
||||
- **Storage Cleanup**: Automatic cleanup of old recordings
|
||||
- **Time Sync**: Automatic NTP synchronization
|
||||
- **Health Checks**: Built-in system monitoring
|
||||
|
||||
### Troubleshooting
|
||||
- **Test Suite**: `python test_system.py`
|
||||
- **Time Check**: `python check_time.py`
|
||||
- **API Health**: `curl http://localhost:8000/health`
|
||||
- **Debug Mode**: `python main.py --log-level DEBUG`
|
||||
|
||||
## 🎯 Production Readiness
|
||||
|
||||
### ✅ All Tests Passing
|
||||
- System initialization: ✅
|
||||
- Camera discovery: ✅ (2 cameras found)
|
||||
- MQTT configuration: ✅
|
||||
- Storage setup: ✅
|
||||
- Time synchronization: ✅
|
||||
- API endpoints: ✅
|
||||
|
||||
### ✅ Documentation Complete
|
||||
- Installation guide: ✅
|
||||
- Configuration reference: ✅
|
||||
- API documentation: ✅
|
||||
- Troubleshooting guide: ✅
|
||||
- Integration examples: ✅
|
||||
|
||||
### ✅ Production Features
|
||||
- Error handling: ✅
|
||||
- Logging system: ✅
|
||||
- Time synchronization: ✅
|
||||
- Storage management: ✅
|
||||
- API security: ✅
|
||||
- Performance monitoring: ✅
|
||||
|
||||
## 🚀 Next Steps
|
||||
|
||||
The system is now ready for:
|
||||
|
||||
1. **Production Deployment**: Deploy on target hardware
|
||||
2. **Dashboard Integration**: Connect to React + Supabase dashboard
|
||||
3. **MQTT Configuration**: Connect to production MQTT broker
|
||||
4. **Camera Calibration**: Fine-tune camera settings for production
|
||||
5. **Monitoring Setup**: Configure production monitoring and alerts
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For ongoing support:
|
||||
- **Documentation**: Complete README.md with troubleshooting
|
||||
- **Test Suite**: Comprehensive diagnostic tools
|
||||
- **Logging**: Detailed system logs for debugging
|
||||
- **API Health**: Built-in health check endpoints
|
||||
|
||||
---
|
||||
|
||||
**🎊 PROJECT STATUS: COMPLETE AND PRODUCTION-READY! 🎊**
|
||||
|
||||
The USDA Vision Camera System is fully implemented, tested, and documented. All original requirements have been met, and the system is ready for production deployment with your React dashboard integration.
|
||||
|
||||
**Key Achievements:**
|
||||
- ✅ Dual MQTT topic monitoring
|
||||
- ✅ Automatic camera recording
|
||||
- ✅ Atlanta timezone synchronization
|
||||
- ✅ Complete REST API
|
||||
- ✅ Comprehensive documentation
|
||||
- ✅ Production-ready deployment
|
||||
276
camera-management-api/docs/REACT_INTEGRATION_GUIDE.md
Normal file
276
camera-management-api/docs/REACT_INTEGRATION_GUIDE.md
Normal file
@@ -0,0 +1,276 @@
|
||||
# 🚀 React Frontend Integration Guide - MP4 Update
|
||||
|
||||
## 🎯 Quick Summary for React Team
|
||||
|
||||
The camera system now records in **MP4 format** instead of AVI. This provides better web compatibility and smaller file sizes.
|
||||
|
||||
## 🔄 What You Need to Update
|
||||
|
||||
### 1. File Extension Handling
|
||||
```javascript
|
||||
// OLD: Only checked for .avi
|
||||
const isVideoFile = (filename) => filename.endsWith('.avi');
|
||||
|
||||
// NEW: Check for both formats
|
||||
const isVideoFile = (filename) => {
|
||||
return filename.endsWith('.mp4') || filename.endsWith('.avi');
|
||||
};
|
||||
|
||||
// Video MIME types
|
||||
const getVideoMimeType = (filename) => {
|
||||
if (filename.endsWith('.mp4')) return 'video/mp4';
|
||||
if (filename.endsWith('.avi')) return 'video/x-msvideo';
|
||||
return 'video/mp4'; // default for new files
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Video Player Component
|
||||
```jsx
|
||||
// MP4 files work better with HTML5 video
|
||||
const VideoPlayer = ({ videoUrl, filename }) => {
|
||||
const mimeType = getVideoMimeType(filename);
|
||||
|
||||
return (
|
||||
<video controls width="100%" height="auto">
|
||||
<source src={videoUrl} type={mimeType} />
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Camera Configuration Interface
|
||||
Add these new fields to your camera config forms:
|
||||
|
||||
```jsx
|
||||
const CameraConfigForm = () => {
|
||||
const [config, setConfig] = useState({
|
||||
// ... existing fields
|
||||
video_format: 'mp4', // 'mp4' or 'avi'
|
||||
video_codec: 'mp4v', // 'mp4v', 'XVID', 'MJPG'
|
||||
video_quality: 95 // 0-100
|
||||
});
|
||||
|
||||
return (
|
||||
<form>
|
||||
{/* ... existing fields */}
|
||||
|
||||
<div className="video-settings">
|
||||
<h3>Video Recording Settings</h3>
|
||||
|
||||
<select
|
||||
value={config.video_format}
|
||||
onChange={(e) => setConfig({...config, video_format: e.target.value})}
|
||||
>
|
||||
<option value="mp4">MP4 (Recommended)</option>
|
||||
<option value="avi">AVI (Legacy)</option>
|
||||
</select>
|
||||
|
||||
<select
|
||||
value={config.video_codec}
|
||||
onChange={(e) => setConfig({...config, video_codec: e.target.value})}
|
||||
>
|
||||
<option value="mp4v">MPEG-4 (mp4v)</option>
|
||||
<option value="XVID">Xvid</option>
|
||||
<option value="MJPG">Motion JPEG</option>
|
||||
</select>
|
||||
|
||||
<input
|
||||
type="range"
|
||||
min="50"
|
||||
max="100"
|
||||
value={config.video_quality}
|
||||
onChange={(e) => setConfig({...config, video_quality: parseInt(e.target.value)})}
|
||||
/>
|
||||
<label>Quality: {config.video_quality}%</label>
|
||||
|
||||
<div className="warning">
|
||||
⚠️ Video format changes require camera restart
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## 📡 API Response Changes
|
||||
|
||||
### Camera Configuration Response
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "blower_separator",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 0.3,
|
||||
"gain": 4.0,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"video_format": "mp4",
|
||||
"video_codec": "mp4v",
|
||||
"video_quality": 95,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
|
||||
// ... other existing fields
|
||||
}
|
||||
```
|
||||
|
||||
### Video File Listings
|
||||
```json
|
||||
{
|
||||
"videos": [
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.mp4",
|
||||
"filename": "camera1_recording_20250804_143022.mp4",
|
||||
"format": "mp4",
|
||||
"file_size_bytes": 31457280,
|
||||
"created_at": "2025-08-04T14:30:22"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 🎨 UI/UX Improvements
|
||||
|
||||
### File Size Display
|
||||
```javascript
|
||||
// MP4 files are ~40% smaller
|
||||
const formatFileSize = (bytes) => {
|
||||
const mb = bytes / (1024 * 1024);
|
||||
return `${mb.toFixed(1)} MB`;
|
||||
};
|
||||
|
||||
// Show format in file listings
|
||||
const FileListItem = ({ video }) => (
|
||||
<div className="file-item">
|
||||
<span className="filename">{video.filename}</span>
|
||||
<span className={`format ${video.format}`}>
|
||||
{video.format.toUpperCase()}
|
||||
</span>
|
||||
<span className="size">{formatFileSize(video.file_size_bytes)}</span>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
### Format Indicators
|
||||
```css
|
||||
.format.mp4 {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.format.avi {
|
||||
background: #FF9800;
|
||||
color: white;
|
||||
padding: 2px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
```
|
||||
|
||||
## ⚡ Performance Benefits
|
||||
|
||||
### Streaming Improvements
|
||||
- **Faster Loading**: MP4 files start playing sooner
|
||||
- **Better Seeking**: More responsive video scrubbing
|
||||
- **Mobile Friendly**: Better iOS/Android compatibility
|
||||
- **Bandwidth Savings**: 40% smaller files = faster transfers
|
||||
|
||||
### Implementation Tips
|
||||
```javascript
|
||||
// Preload video metadata for better UX
|
||||
const VideoThumbnail = ({ videoUrl }) => (
|
||||
<video
|
||||
preload="metadata"
|
||||
poster={`${videoUrl}?t=1`} // Thumbnail at 1 second
|
||||
onLoadedMetadata={(e) => {
|
||||
console.log('Duration:', e.target.duration);
|
||||
}}
|
||||
>
|
||||
<source src={videoUrl} type="video/mp4" />
|
||||
</video>
|
||||
);
|
||||
```
|
||||
|
||||
## 🔧 Configuration Management
|
||||
|
||||
### Restart Warning Component
|
||||
```jsx
|
||||
const RestartWarning = ({ show }) => {
|
||||
if (!show) return null;
|
||||
|
||||
return (
|
||||
<div className="alert alert-warning">
|
||||
<strong>⚠️ Restart Required</strong>
|
||||
<p>Video format changes require a camera service restart to take effect.</p>
|
||||
<button onClick={handleRestart}>Restart Camera Service</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Settings Validation
|
||||
```javascript
|
||||
const validateVideoSettings = (settings) => {
|
||||
const errors = {};
|
||||
|
||||
if (!['mp4', 'avi'].includes(settings.video_format)) {
|
||||
errors.video_format = 'Must be mp4 or avi';
|
||||
}
|
||||
|
||||
if (!['mp4v', 'XVID', 'MJPG'].includes(settings.video_codec)) {
|
||||
errors.video_codec = 'Invalid codec';
|
||||
}
|
||||
|
||||
if (settings.video_quality < 50 || settings.video_quality > 100) {
|
||||
errors.video_quality = 'Quality must be between 50-100';
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
```
|
||||
|
||||
## 📱 Mobile Considerations
|
||||
|
||||
### Responsive Video Player
|
||||
```jsx
|
||||
const ResponsiveVideoPlayer = ({ videoUrl, filename }) => (
|
||||
<div className="video-container">
|
||||
<video
|
||||
controls
|
||||
playsInline // Important for iOS
|
||||
preload="metadata"
|
||||
style={{ width: '100%', height: 'auto' }}
|
||||
>
|
||||
<source src={videoUrl} type={getVideoMimeType(filename)} />
|
||||
<p>Your browser doesn't support HTML5 video.</p>
|
||||
</video>
|
||||
</div>
|
||||
);
|
||||
```
|
||||
|
||||
## 🧪 Testing Checklist
|
||||
|
||||
- [ ] Video playback works with new MP4 files
|
||||
- [ ] File extension filtering includes both .mp4 and .avi
|
||||
- [ ] Camera configuration UI shows video format options
|
||||
- [ ] Restart warning appears for video format changes
|
||||
- [ ] File size displays are updated for smaller MP4 files
|
||||
- [ ] Mobile video playback works correctly
|
||||
- [ ] Video streaming performance is improved
|
||||
- [ ] Backward compatibility with existing AVI files
|
||||
|
||||
## 📞 Support
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. **Video won't play**: Check browser console for codec errors
|
||||
2. **File size unexpected**: Verify quality settings in camera config
|
||||
3. **Streaming slow**: Compare MP4 vs AVI performance
|
||||
4. **Mobile issues**: Ensure `playsInline` attribute is set
|
||||
|
||||
The MP4 update provides significant improvements in web compatibility and performance while maintaining full backward compatibility with existing AVI files.
|
||||
100
camera-management-api/docs/README.md
Normal file
100
camera-management-api/docs/README.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# USDA Vision Camera System - Documentation
|
||||
|
||||
This directory contains detailed documentation for the USDA Vision Camera System.
|
||||
|
||||
## Documentation Files
|
||||
|
||||
### 🚀 [API_DOCUMENTATION.md](API_DOCUMENTATION.md) **⭐ NEW**
|
||||
**Complete API reference documentation** covering all endpoints, features, and recent enhancements:
|
||||
- System status and health monitoring
|
||||
- Camera management and configuration
|
||||
- Recording control with dynamic settings
|
||||
- Auto-recording management
|
||||
- MQTT and machine status
|
||||
- Storage and file management
|
||||
- Camera recovery and diagnostics
|
||||
- Live streaming capabilities
|
||||
- WebSocket real-time updates
|
||||
- Quick start examples and migration notes
|
||||
|
||||
### ⚡ [API_QUICK_REFERENCE.md](API_QUICK_REFERENCE.md) **⭐ NEW**
|
||||
**Quick reference card** for the most commonly used API endpoints with curl examples and response formats.
|
||||
|
||||
### 📋 [PROJECT_COMPLETE.md](PROJECT_COMPLETE.md)
|
||||
Complete project overview and final status documentation. Contains:
|
||||
- Project completion status
|
||||
- Final system architecture
|
||||
- Deployment instructions
|
||||
- Production readiness checklist
|
||||
|
||||
### 🎥 [MP4_FORMAT_UPDATE.md](MP4_FORMAT_UPDATE.md) **⭐ NEW**
|
||||
**Frontend integration guide** for the MP4 video format update:
|
||||
- Video format changes from AVI to MP4
|
||||
- Frontend implementation checklist
|
||||
- API response updates
|
||||
- Performance benefits and browser compatibility
|
||||
|
||||
### 🚀 [REACT_INTEGRATION_GUIDE.md](REACT_INTEGRATION_GUIDE.md) **⭐ NEW**
|
||||
**Quick reference for React developers** implementing the MP4 format changes:
|
||||
- Code examples and components
|
||||
- File handling updates
|
||||
- Configuration interface
|
||||
- Testing checklist
|
||||
|
||||
### 📋 [CURRENT_CONFIGURATION.md](CURRENT_CONFIGURATION.md) **⭐ NEW**
|
||||
**Complete current system configuration reference**:
|
||||
- Exact config.json structure with all current values
|
||||
- Field-by-field documentation
|
||||
- Camera-specific settings comparison
|
||||
- MQTT topics and machine mappings
|
||||
|
||||
### 🎬 [VIDEO_STREAMING.md](VIDEO_STREAMING.md) **⭐ UPDATED**
|
||||
**Complete video streaming module documentation**:
|
||||
- Comprehensive API endpoint documentation
|
||||
- Authentication and security information
|
||||
- Error handling and troubleshooting
|
||||
- Performance optimization guidelines
|
||||
|
||||
### 🤖 [AI_AGENT_VIDEO_INTEGRATION_GUIDE.md](AI_AGENT_VIDEO_INTEGRATION_GUIDE.md) **⭐ NEW**
|
||||
**Complete integration guide for AI agents and external systems**:
|
||||
- Step-by-step integration workflow
|
||||
- Programming language examples (Python, JavaScript)
|
||||
- Error handling and debugging strategies
|
||||
- Performance optimization recommendations
|
||||
|
||||
### 🔧 [API_CHANGES_SUMMARY.md](API_CHANGES_SUMMARY.md)
|
||||
Summary of API changes and enhancements made to the system.
|
||||
|
||||
### 📷 [CAMERA_RECOVERY_GUIDE.md](CAMERA_RECOVERY_GUIDE.md)
|
||||
Guide for camera recovery procedures and troubleshooting camera-related issues.
|
||||
|
||||
### 📡 [MQTT_LOGGING_GUIDE.md](MQTT_LOGGING_GUIDE.md)
|
||||
Comprehensive guide for MQTT logging configuration and troubleshooting.
|
||||
|
||||
## Main Documentation
|
||||
|
||||
The main system documentation is located in the root directory:
|
||||
- **[../README.md](../README.md)** - Primary system documentation with installation, configuration, and usage instructions
|
||||
|
||||
## Additional Resources
|
||||
|
||||
### Demo Code
|
||||
- **[../demos/](../demos/)** - Demo scripts and camera SDK examples
|
||||
|
||||
### Test Files
|
||||
- **[../tests/](../tests/)** - Test scripts and legacy test files
|
||||
|
||||
### Jupyter Notebooks
|
||||
- **[../notebooks/](../notebooks/)** - Interactive notebooks for system exploration and testing
|
||||
|
||||
## Quick Links
|
||||
|
||||
- [System Installation](../README.md#installation)
|
||||
- [Configuration Guide](../README.md#configuration)
|
||||
- [API Documentation](../README.md#api-reference)
|
||||
- [Troubleshooting](../README.md#troubleshooting)
|
||||
- [Camera SDK Examples](../demos/camera_sdk_examples/)
|
||||
|
||||
## Support
|
||||
|
||||
For technical support and questions, refer to the main [README.md](../README.md) troubleshooting section or check the system logs.
|
||||
601
camera-management-api/docs/VIDEO_STREAMING.md
Normal file
601
camera-management-api/docs/VIDEO_STREAMING.md
Normal file
@@ -0,0 +1,601 @@
|
||||
# 🎬 Video Streaming Module
|
||||
|
||||
The USDA Vision Camera System now includes a modular video streaming system that provides YouTube-like video playback capabilities for your React web application.
|
||||
|
||||
## 🌟 Features
|
||||
|
||||
- **Progressive Streaming** - True chunked streaming for web browsers (no download required)
|
||||
- **HTTP Range Request Support** - Enables seeking and progressive download with 206 Partial Content
|
||||
- **Native MP4 Support** - Direct streaming of MP4 files optimized for web playback
|
||||
- **Memory Efficient** - 8KB chunked delivery, no large file loading into memory
|
||||
- **Browser Compatible** - Works with HTML5 `<video>` tag in all modern browsers
|
||||
- **Intelligent Caching** - Optimized streaming performance with byte-range caching
|
||||
- **Thumbnail Generation** - Extract preview images from videos
|
||||
- **Modular Architecture** - Clean separation of concerns
|
||||
- **No Authentication Required** - Open access for internal network use
|
||||
- **CORS Enabled** - Ready for web browser integration
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
The video module follows clean architecture principles:
|
||||
|
||||
```
|
||||
usda_vision_system/video/
|
||||
├── domain/ # Business logic (pure Python)
|
||||
├── infrastructure/ # External dependencies (OpenCV, FFmpeg)
|
||||
├── application/ # Use cases and orchestration
|
||||
├── presentation/ # HTTP controllers and API routes
|
||||
└── integration.py # Dependency injection and composition
|
||||
```
|
||||
|
||||
## 🚀 API Endpoints
|
||||
|
||||
### List Videos
|
||||
```http
|
||||
GET /videos/
|
||||
```
|
||||
**Query Parameters:**
|
||||
- `camera_name` (optional): Filter by camera name
|
||||
- `start_date` (optional): Filter videos created after this date (ISO format: 2025-08-04T14:30:22)
|
||||
- `end_date` (optional): Filter videos created before this date (ISO format: 2025-08-04T14:30:22)
|
||||
- `limit` (optional): Maximum results (default: 50, max: 1000)
|
||||
- `include_metadata` (optional): Include video metadata (default: false)
|
||||
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl "http://localhost:8000/videos/?camera_name=camera1&include_metadata=true&limit=10"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"videos": [
|
||||
{
|
||||
"file_id": "camera1_auto_blower_separator_20250804_143022.mp4",
|
||||
"camera_name": "camera1",
|
||||
"filename": "camera1_auto_blower_separator_20250804_143022.mp4",
|
||||
"file_size_bytes": 31457280,
|
||||
"format": "mp4",
|
||||
"status": "completed",
|
||||
"created_at": "2025-08-04T14:30:22",
|
||||
"start_time": "2025-08-04T14:30:22",
|
||||
"end_time": "2025-08-04T14:32:22",
|
||||
"machine_trigger": "blower_separator",
|
||||
"is_streamable": true,
|
||||
"needs_conversion": false,
|
||||
"metadata": {
|
||||
"duration_seconds": 120.5,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"fps": 30.0,
|
||||
"codec": "mp4v",
|
||||
"bitrate": 5000000,
|
||||
"aspect_ratio": 1.777
|
||||
}
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### Stream Video
|
||||
```http
|
||||
GET /videos/{file_id}/stream
|
||||
```
|
||||
**Headers:**
|
||||
- `Range: bytes=0-1023` (optional): Request specific byte range for seeking
|
||||
|
||||
**Example Requests:**
|
||||
```bash
|
||||
# Stream entire video (progressive streaming)
|
||||
curl http://localhost:8000/videos/camera1_auto_blower_separator_20250805_123329.mp4/stream
|
||||
|
||||
# Stream specific byte range (for seeking)
|
||||
curl -H "Range: bytes=0-1023" \
|
||||
http://localhost:8000/videos/camera1_auto_blower_separator_20250805_123329.mp4/stream
|
||||
```
|
||||
|
||||
**Response Headers:**
|
||||
- `Accept-Ranges: bytes`
|
||||
- `Content-Length: {size}`
|
||||
- `Content-Range: bytes {start}-{end}/{total}` (for range requests)
|
||||
- `Cache-Control: public, max-age=3600`
|
||||
- `Content-Type: video/mp4`
|
||||
|
||||
**Streaming Implementation:**
|
||||
- ✅ **Progressive Streaming**: Uses FastAPI `StreamingResponse` with 8KB chunks
|
||||
- ✅ **HTTP Range Requests**: Returns 206 Partial Content for seeking
|
||||
- ✅ **Memory Efficient**: No large file loading, streams directly from disk
|
||||
- ✅ **Browser Compatible**: Works with HTML5 `<video>` tag playback
|
||||
- ✅ **Chunked Delivery**: Optimal 8KB chunk size for smooth playback
|
||||
- ✅ **CORS Enabled**: Ready for web browser integration
|
||||
|
||||
**Response Status Codes:**
|
||||
- `200 OK`: Full video streaming (progressive chunks)
|
||||
- `206 Partial Content`: Range request successful
|
||||
- `404 Not Found`: Video not found or not streamable
|
||||
- `416 Range Not Satisfiable`: Invalid range request
|
||||
|
||||
### Get Video Info
|
||||
```http
|
||||
GET /videos/{file_id}
|
||||
```
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl http://localhost:8000/videos/camera1_recording_20250804_143022.avi
|
||||
```
|
||||
|
||||
**Response includes complete metadata:**
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"camera_name": "camera1",
|
||||
"filename": "camera1_recording_20250804_143022.avi",
|
||||
"file_size_bytes": 52428800,
|
||||
"format": "avi",
|
||||
"status": "completed",
|
||||
"created_at": "2025-08-04T14:30:22",
|
||||
"start_time": "2025-08-04T14:30:22",
|
||||
"end_time": "2025-08-04T14:32:22",
|
||||
"machine_trigger": "vibratory_conveyor",
|
||||
"is_streamable": true,
|
||||
"needs_conversion": true,
|
||||
"metadata": {
|
||||
"duration_seconds": 120.5,
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"fps": 30.0,
|
||||
"codec": "XVID",
|
||||
"bitrate": 5000000,
|
||||
"aspect_ratio": 1.777
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Get Thumbnail
|
||||
```http
|
||||
GET /videos/{file_id}/thumbnail?timestamp=5.0&width=320&height=240
|
||||
```
|
||||
**Query Parameters:**
|
||||
- `timestamp` (optional): Time position in seconds to extract thumbnail from (default: 1.0)
|
||||
- `width` (optional): Thumbnail width in pixels (default: 320)
|
||||
- `height` (optional): Thumbnail height in pixels (default: 240)
|
||||
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl "http://localhost:8000/videos/camera1_recording_20250804_143022.avi/thumbnail?timestamp=5.0&width=320&height=240" \
|
||||
--output thumbnail.jpg
|
||||
```
|
||||
|
||||
**Response**: JPEG image data with caching headers
|
||||
- `Content-Type: image/jpeg`
|
||||
- `Cache-Control: public, max-age=3600`
|
||||
|
||||
### Streaming Info
|
||||
```http
|
||||
GET /videos/{file_id}/info
|
||||
```
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl http://localhost:8000/videos/camera1_recording_20250804_143022.avi/info
|
||||
```
|
||||
|
||||
**Response**: Technical streaming details
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"file_size_bytes": 52428800,
|
||||
"content_type": "video/x-msvideo",
|
||||
"supports_range_requests": true,
|
||||
"chunk_size_bytes": 262144
|
||||
}
|
||||
```
|
||||
|
||||
### Video Validation
|
||||
```http
|
||||
POST /videos/{file_id}/validate
|
||||
```
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/videos/camera1_recording_20250804_143022.avi/validate
|
||||
```
|
||||
|
||||
**Response**: Validation status
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"is_valid": true
|
||||
}
|
||||
```
|
||||
|
||||
### Cache Management
|
||||
```http
|
||||
POST /videos/{file_id}/cache/invalidate
|
||||
```
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/videos/camera1_recording_20250804_143022.avi/cache/invalidate
|
||||
```
|
||||
|
||||
**Response**: Cache invalidation status
|
||||
```json
|
||||
{
|
||||
"file_id": "camera1_recording_20250804_143022.avi",
|
||||
"cache_invalidated": true
|
||||
}
|
||||
```
|
||||
|
||||
### Admin: Cache Cleanup
|
||||
```http
|
||||
POST /admin/videos/cache/cleanup?max_size_mb=100
|
||||
```
|
||||
**Example Request:**
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/admin/videos/cache/cleanup?max_size_mb=100"
|
||||
```
|
||||
|
||||
**Response**: Cache cleanup results
|
||||
```json
|
||||
{
|
||||
"cache_cleaned": true,
|
||||
"entries_removed": 15,
|
||||
"max_size_mb": 100
|
||||
}
|
||||
```
|
||||
|
||||
## 🌐 React Integration
|
||||
|
||||
### Basic Video Player
|
||||
```jsx
|
||||
function VideoPlayer({ fileId }) {
|
||||
return (
|
||||
<video
|
||||
controls
|
||||
width="100%"
|
||||
preload="metadata"
|
||||
style={{ maxWidth: '800px' }}
|
||||
>
|
||||
<source
|
||||
src={`${API_BASE_URL}/videos/${fileId}/stream`}
|
||||
type="video/mp4"
|
||||
/>
|
||||
Your browser does not support video playback.
|
||||
</video>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Advanced Player with Thumbnail
|
||||
```jsx
|
||||
function VideoPlayerWithThumbnail({ fileId }) {
|
||||
const [thumbnail, setThumbnail] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetch(`${API_BASE_URL}/videos/${fileId}/thumbnail`)
|
||||
.then(response => response.blob())
|
||||
.then(blob => setThumbnail(URL.createObjectURL(blob)));
|
||||
}, [fileId]);
|
||||
|
||||
return (
|
||||
<video controls width="100%" poster={thumbnail}>
|
||||
<source
|
||||
src={`${API_BASE_URL}/videos/${fileId}/stream`}
|
||||
type="video/mp4"
|
||||
/>
|
||||
</video>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Video List Component
|
||||
```jsx
|
||||
function VideoList({ cameraName }) {
|
||||
const [videos, setVideos] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams();
|
||||
if (cameraName) params.append('camera_name', cameraName);
|
||||
params.append('include_metadata', 'true');
|
||||
|
||||
fetch(`${API_BASE_URL}/videos/?${params}`)
|
||||
.then(response => response.json())
|
||||
.then(data => setVideos(data.videos));
|
||||
}, [cameraName]);
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{videos.map(video => (
|
||||
<VideoCard key={video.file_id} video={video} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
The video module is automatically initialized when the API server starts. Configuration options:
|
||||
|
||||
```python
|
||||
# In your API server initialization
|
||||
video_module = create_video_module(
|
||||
config=config,
|
||||
storage_manager=storage_manager,
|
||||
enable_caching=True, # Enable streaming cache
|
||||
enable_conversion=True # Enable format conversion
|
||||
)
|
||||
```
|
||||
|
||||
### Configuration Parameters
|
||||
- **`enable_caching`**: Enable/disable intelligent byte-range caching (default: True)
|
||||
- **`cache_size_mb`**: Maximum cache size in MB (default: 100)
|
||||
- **`cache_max_age_minutes`**: Cache entry expiration time (default: 30)
|
||||
- **`enable_conversion`**: Enable/disable automatic AVI to MP4 conversion (default: True)
|
||||
- **`conversion_quality`**: Video conversion quality: "low", "medium", "high" (default: "medium")
|
||||
|
||||
### System Requirements
|
||||
- **OpenCV**: Required for thumbnail generation and metadata extraction
|
||||
- **FFmpeg**: Optional, for video format conversion (graceful fallback if not available)
|
||||
- **Storage**: Sufficient disk space for video files and cache
|
||||
- **Memory**: Recommended 2GB+ RAM for caching and video processing
|
||||
|
||||
## 🔐 Authentication & Security
|
||||
|
||||
### Current Security Model
|
||||
**⚠️ IMPORTANT: No authentication is currently implemented.**
|
||||
|
||||
- **Open Access**: All video streaming endpoints are publicly accessible
|
||||
- **CORS Policy**: Currently set to allow all origins (`allow_origins=["*"]`)
|
||||
- **Network Security**: Designed for internal network use only
|
||||
- **No API Keys**: No authentication tokens or API keys required
|
||||
- **No Rate Limiting**: No request rate limiting currently implemented
|
||||
|
||||
### Security Considerations for Production
|
||||
|
||||
#### For Internal Network Deployment
|
||||
```bash
|
||||
# Current configuration is suitable for:
|
||||
# - Internal corporate networks
|
||||
# - Isolated network segments
|
||||
# - Development and testing environments
|
||||
```
|
||||
|
||||
#### For External Access (Recommendations)
|
||||
If you need to expose the video streaming API externally, consider implementing:
|
||||
|
||||
1. **Authentication Layer**
|
||||
```python
|
||||
# Example: Add JWT authentication
|
||||
from fastapi import Depends, HTTPException
|
||||
from fastapi.security import HTTPBearer
|
||||
|
||||
security = HTTPBearer()
|
||||
|
||||
async def verify_token(token: str = Depends(security)):
|
||||
# Implement token verification logic
|
||||
pass
|
||||
```
|
||||
|
||||
2. **CORS Configuration**
|
||||
```python
|
||||
# Restrict CORS to specific domains
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["https://yourdomain.com"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["GET", "POST"],
|
||||
allow_headers=["*"]
|
||||
)
|
||||
```
|
||||
|
||||
3. **Rate Limiting**
|
||||
```python
|
||||
# Example: Add rate limiting
|
||||
from slowapi import Limiter
|
||||
|
||||
limiter = Limiter(key_func=get_remote_address)
|
||||
|
||||
@app.get("/videos/")
|
||||
@limiter.limit("10/minute")
|
||||
async def list_videos():
|
||||
pass
|
||||
```
|
||||
|
||||
4. **Network Security**
|
||||
- Use HTTPS/TLS for encrypted communication
|
||||
- Implement firewall rules to restrict access
|
||||
- Consider VPN access for remote users
|
||||
- Use reverse proxy (nginx) for additional security
|
||||
|
||||
### Access Control Summary
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Current Access Model │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Authentication: ❌ None │
|
||||
│ Authorization: ❌ None │
|
||||
│ CORS: ✅ Enabled (all origins) │
|
||||
│ Rate Limiting: ❌ None │
|
||||
│ HTTPS: ⚠️ Depends on deployment │
|
||||
│ Network Security: ⚠️ Firewall/VPN recommended │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 📊 Performance
|
||||
|
||||
- **Caching**: Intelligent byte-range caching reduces disk I/O
|
||||
- **Adaptive Chunking**: Optimal chunk sizes based on file size
|
||||
- **Range Requests**: Only download needed portions
|
||||
- **Format Conversion**: Automatic conversion to web-compatible formats
|
||||
|
||||
## 🛠️ Service Management
|
||||
|
||||
### Restart Service
|
||||
```bash
|
||||
sudo systemctl restart usda-vision-camera
|
||||
```
|
||||
|
||||
### Check Status
|
||||
```bash
|
||||
# Check video module status
|
||||
curl http://localhost:8000/system/video-module
|
||||
|
||||
# Check available videos
|
||||
curl http://localhost:8000/videos/
|
||||
```
|
||||
|
||||
### Logs
|
||||
```bash
|
||||
sudo journalctl -u usda-vision-camera -f
|
||||
```
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
Run the video module tests:
|
||||
```bash
|
||||
cd /home/alireza/USDA-vision-cameras
|
||||
PYTHONPATH=/home/alireza/USDA-vision-cameras python tests/test_video_module.py
|
||||
```
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Video Not Playing
|
||||
1. **Check if file exists**: `GET /videos/{file_id}`
|
||||
```bash
|
||||
curl http://localhost:8000/videos/camera1_recording_20250804_143022.avi
|
||||
```
|
||||
2. **Verify streaming info**: `GET /videos/{file_id}/info`
|
||||
```bash
|
||||
curl http://localhost:8000/videos/camera1_recording_20250804_143022.avi/info
|
||||
```
|
||||
3. **Test direct stream**: `GET /videos/{file_id}/stream`
|
||||
```bash
|
||||
curl -I http://localhost:8000/videos/camera1_recording_20250804_143022.avi/stream
|
||||
```
|
||||
4. **Validate video file**: `POST /videos/{file_id}/validate`
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/videos/camera1_recording_20250804_143022.avi/validate
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
1. **Check cache status**: Clean up cache if needed
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/admin/videos/cache/cleanup?max_size_mb=100"
|
||||
```
|
||||
2. **Monitor system resources**: Check CPU, memory, and disk usage
|
||||
3. **Adjust cache size**: Modify configuration parameters
|
||||
4. **Invalidate specific cache**: For updated files
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/videos/{file_id}/cache/invalidate
|
||||
```
|
||||
|
||||
### Format Issues
|
||||
- **AVI files**: Automatically converted to MP4 for web compatibility
|
||||
- **Conversion requires FFmpeg**: Optional dependency with graceful fallback
|
||||
- **Supported formats**: AVI (with conversion), MP4 (native), WebM (native)
|
||||
|
||||
### Common HTTP Status Codes
|
||||
- **200**: Success - Video streamed successfully
|
||||
- **206**: Partial Content - Range request successful
|
||||
- **404**: Not Found - Video file doesn't exist or isn't streamable
|
||||
- **416**: Range Not Satisfiable - Invalid range request
|
||||
- **500**: Internal Server Error - Failed to read video data or generate thumbnail
|
||||
|
||||
### Browser Compatibility
|
||||
- **Chrome/Chromium**: Full support for MP4 and range requests
|
||||
- **Firefox**: Full support for MP4 and range requests
|
||||
- **Safari**: Full support for MP4 and range requests
|
||||
- **Edge**: Full support for MP4 and range requests
|
||||
- **Mobile browsers**: Generally good support for MP4 streaming
|
||||
|
||||
### Error Scenarios and Solutions
|
||||
|
||||
#### Video File Issues
|
||||
```bash
|
||||
# Problem: Video not found (404)
|
||||
curl http://localhost:8000/videos/nonexistent_video.mp4
|
||||
# Response: {"detail": "Video nonexistent_video.mp4 not found"}
|
||||
# Solution: Verify file_id exists using list endpoint
|
||||
|
||||
# Problem: Video not streamable
|
||||
curl http://localhost:8000/videos/corrupted_video.avi/stream
|
||||
# Response: {"detail": "Video corrupted_video.avi not found or not streamable"}
|
||||
# Solution: Use validation endpoint to check file integrity
|
||||
```
|
||||
|
||||
#### Range Request Issues
|
||||
```bash
|
||||
# Problem: Invalid range request (416)
|
||||
curl -H "Range: bytes=999999999-" http://localhost:8000/videos/small_video.mp4/stream
|
||||
# Response: {"detail": "Invalid range request: Range exceeds file size"}
|
||||
# Solution: Check file size first using /info endpoint
|
||||
|
||||
# Problem: Malformed range header
|
||||
curl -H "Range: invalid-range" http://localhost:8000/videos/video.mp4/stream
|
||||
# Response: {"detail": "Invalid range request: Malformed range header"}
|
||||
# Solution: Use proper range format: "bytes=start-end"
|
||||
```
|
||||
|
||||
#### Thumbnail Generation Issues
|
||||
```bash
|
||||
# Problem: Thumbnail generation failed (404)
|
||||
curl http://localhost:8000/videos/audio_only.mp4/thumbnail
|
||||
# Response: {"detail": "Could not generate thumbnail for audio_only.mp4"}
|
||||
# Solution: Verify video has visual content and is not audio-only
|
||||
|
||||
# Problem: Invalid timestamp
|
||||
curl "http://localhost:8000/videos/short_video.mp4/thumbnail?timestamp=999"
|
||||
# Response: Returns thumbnail from last available frame
|
||||
# Solution: Check video duration first using metadata
|
||||
```
|
||||
|
||||
#### System Resource Issues
|
||||
```bash
|
||||
# Problem: Cache full or system overloaded (500)
|
||||
curl http://localhost:8000/videos/large_video.mp4/stream
|
||||
# Response: {"detail": "Failed to read video data"}
|
||||
# Solution: Clean cache or wait for system resources
|
||||
curl -X POST "http://localhost:8000/admin/videos/cache/cleanup?max_size_mb=50"
|
||||
```
|
||||
|
||||
### Debugging Workflow
|
||||
```bash
|
||||
# Step 1: Check system health
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# Step 2: Verify video exists and get info
|
||||
curl http://localhost:8000/videos/your_video_id
|
||||
|
||||
# Step 3: Check streaming capabilities
|
||||
curl http://localhost:8000/videos/your_video_id/info
|
||||
|
||||
# Step 4: Validate video file
|
||||
curl -X POST http://localhost:8000/videos/your_video_id/validate
|
||||
|
||||
# Step 5: Test basic streaming
|
||||
curl -I http://localhost:8000/videos/your_video_id/stream
|
||||
|
||||
# Step 6: Test range request
|
||||
curl -I -H "Range: bytes=0-1023" http://localhost:8000/videos/your_video_id/stream
|
||||
```
|
||||
|
||||
### Performance Monitoring
|
||||
```bash
|
||||
# Monitor cache usage
|
||||
curl -X POST "http://localhost:8000/admin/videos/cache/cleanup?max_size_mb=100"
|
||||
|
||||
# Check system resources
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# Monitor video module status
|
||||
curl http://localhost:8000/videos/ | jq '.total_count'
|
||||
```
|
||||
|
||||
## 🎯 Next Steps
|
||||
|
||||
1. **Restart the usda-vision-camera service** to enable video streaming
|
||||
2. **Test the endpoints** using curl or your browser
|
||||
3. **Integrate with your React app** using the provided examples
|
||||
4. **Monitor performance** and adjust caching as needed
|
||||
|
||||
The video streaming system is now ready for production use! 🚀
|
||||
302
camera-management-api/docs/WEB_AI_AGENT_VIDEO_INTEGRATION.md
Normal file
302
camera-management-api/docs/WEB_AI_AGENT_VIDEO_INTEGRATION.md
Normal file
@@ -0,0 +1,302 @@
|
||||
# 🤖 Web AI Agent - Video Integration Guide
|
||||
|
||||
This guide provides the essential information for integrating USDA Vision Camera video streaming into your web application.
|
||||
|
||||
## 🎯 Quick Start
|
||||
|
||||
### Video Streaming Status: ✅ READY
|
||||
- **Progressive streaming implemented** - Videos play in browsers (no download)
|
||||
- **86 MP4 files available** - All properly indexed and streamable
|
||||
- **HTTP range requests supported** - Seeking and progressive playback work
|
||||
- **Memory efficient** - 8KB chunked delivery
|
||||
|
||||
## 🚀 API Endpoints
|
||||
|
||||
### Base URL
|
||||
```
|
||||
http://localhost:8000
|
||||
```
|
||||
|
||||
### 1. List Available Videos
|
||||
```http
|
||||
GET /videos/?camera_name={camera}&limit={limit}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
curl "http://localhost:8000/videos/?camera_name=camera1&limit=10"
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"videos": [
|
||||
{
|
||||
"file_id": "camera1_auto_blower_separator_20250805_123329.mp4",
|
||||
"camera_name": "camera1",
|
||||
"file_size_bytes": 1072014489,
|
||||
"format": "mp4",
|
||||
"status": "completed",
|
||||
"is_streamable": true,
|
||||
"created_at": "2025-08-05T12:43:12.631210"
|
||||
}
|
||||
],
|
||||
"total_count": 1
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Stream Video (Progressive)
|
||||
```http
|
||||
GET /videos/{file_id}/stream
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
curl "http://localhost:8000/videos/camera1_auto_blower_separator_20250805_123329.mp4/stream"
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- ✅ Progressive streaming (8KB chunks)
|
||||
- ✅ HTTP range requests (206 Partial Content)
|
||||
- ✅ Browser compatible (HTML5 video)
|
||||
- ✅ Seeking support
|
||||
- ✅ No authentication required
|
||||
|
||||
### 3. Get Video Thumbnail
|
||||
```http
|
||||
GET /videos/{file_id}/thumbnail?timestamp={seconds}&width={px}&height={px}
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
curl "http://localhost:8000/videos/camera1_auto_blower_separator_20250805_123329.mp4/thumbnail?timestamp=5.0&width=320&height=240"
|
||||
```
|
||||
|
||||
## 🌐 Web Integration
|
||||
|
||||
### HTML5 Video Player
|
||||
```html
|
||||
<video controls width="100%" preload="metadata">
|
||||
<source src="http://localhost:8000/videos/{file_id}/stream" type="video/mp4">
|
||||
Your browser does not support video playback.
|
||||
</video>
|
||||
```
|
||||
|
||||
### React Component
|
||||
```jsx
|
||||
function VideoPlayer({ fileId, width = "100%" }) {
|
||||
const streamUrl = `http://localhost:8000/videos/${fileId}/stream`;
|
||||
const thumbnailUrl = `http://localhost:8000/videos/${fileId}/thumbnail`;
|
||||
|
||||
return (
|
||||
<video
|
||||
controls
|
||||
width={width}
|
||||
preload="metadata"
|
||||
poster={thumbnailUrl}
|
||||
style={{ maxWidth: '800px', borderRadius: '8px' }}
|
||||
>
|
||||
<source src={streamUrl} type="video/mp4" />
|
||||
Your browser does not support video playback.
|
||||
</video>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Video List Component
|
||||
```jsx
|
||||
function VideoList({ cameraName = null, limit = 20 }) {
|
||||
const [videos, setVideos] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const params = new URLSearchParams();
|
||||
if (cameraName) params.append('camera_name', cameraName);
|
||||
params.append('limit', limit.toString());
|
||||
|
||||
fetch(`http://localhost:8000/videos/?${params}`)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Filter only streamable MP4 videos
|
||||
const streamableVideos = data.videos.filter(
|
||||
v => v.format === 'mp4' && v.is_streamable
|
||||
);
|
||||
setVideos(streamableVideos);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading videos:', error);
|
||||
setLoading(false);
|
||||
});
|
||||
}, [cameraName, limit]);
|
||||
|
||||
if (loading) return <div>Loading videos...</div>;
|
||||
|
||||
return (
|
||||
<div className="video-grid">
|
||||
{videos.map(video => (
|
||||
<div key={video.file_id} className="video-card">
|
||||
<h3>{video.file_id}</h3>
|
||||
<p>Camera: {video.camera_name}</p>
|
||||
<p>Size: {(video.file_size_bytes / 1024 / 1024).toFixed(1)} MB</p>
|
||||
<VideoPlayer fileId={video.file_id} width="100%" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Available Data
|
||||
|
||||
### Current Video Inventory
|
||||
- **Total Videos**: 161 files
|
||||
- **MP4 Files**: 86 (all streamable ✅)
|
||||
- **AVI Files**: 75 (legacy format, not prioritized)
|
||||
- **Cameras**: camera1, camera2
|
||||
- **Date Range**: July 29 - August 5, 2025
|
||||
|
||||
### Video File Naming Convention
|
||||
```
|
||||
{camera}_{trigger}_{machine}_{YYYYMMDD}_{HHMMSS}.mp4
|
||||
```
|
||||
|
||||
**Examples:**
|
||||
- `camera1_auto_blower_separator_20250805_123329.mp4`
|
||||
- `camera2_auto_vibratory_conveyor_20250805_123042.mp4`
|
||||
- `20250804_161305_manual_camera1_2025-08-04T20-13-09-634Z.mp4`
|
||||
|
||||
### Machine Triggers
|
||||
- `auto_blower_separator` - Automatic recording triggered by blower separator
|
||||
- `auto_vibratory_conveyor` - Automatic recording triggered by vibratory conveyor
|
||||
- `manual` - Manual recording initiated by user
|
||||
|
||||
## 🔧 Technical Details
|
||||
|
||||
### Streaming Implementation
|
||||
- **Method**: FastAPI `StreamingResponse` with async generators
|
||||
- **Chunk Size**: 8KB for optimal performance
|
||||
- **Range Requests**: Full HTTP/1.1 range request support
|
||||
- **Status Codes**: 200 (full), 206 (partial), 404 (not found)
|
||||
- **CORS**: Enabled for all origins
|
||||
- **Caching**: Server-side byte-range caching
|
||||
|
||||
### Browser Compatibility
|
||||
- ✅ Chrome/Chromium
|
||||
- ✅ Firefox
|
||||
- ✅ Safari
|
||||
- ✅ Edge
|
||||
- ✅ Mobile browsers
|
||||
|
||||
### Performance Characteristics
|
||||
- **Memory Usage**: Low (8KB chunks, no large file loading)
|
||||
- **Seeking**: Instant (HTTP range requests)
|
||||
- **Startup Time**: Fast (metadata preload)
|
||||
- **Bandwidth**: Adaptive (only downloads viewed portions)
|
||||
|
||||
## 🛠️ Error Handling
|
||||
|
||||
### Common Scenarios
|
||||
```javascript
|
||||
// Check if video is streamable
|
||||
const checkVideo = async (fileId) => {
|
||||
try {
|
||||
const response = await fetch(`http://localhost:8000/videos/${fileId}`);
|
||||
const video = await response.json();
|
||||
|
||||
if (!video.is_streamable) {
|
||||
console.warn(`Video ${fileId} is not streamable`);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error(`Error checking video ${fileId}:`, error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Handle video loading errors
|
||||
const VideoPlayerWithErrorHandling = ({ fileId }) => {
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const handleError = (e) => {
|
||||
console.error('Video playback error:', e);
|
||||
setError('Failed to load video. Please try again.');
|
||||
};
|
||||
|
||||
if (error) {
|
||||
return <div className="error">❌ {error}</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<video
|
||||
controls
|
||||
onError={handleError}
|
||||
src={`http://localhost:8000/videos/${fileId}/stream`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### HTTP Status Codes
|
||||
- `200 OK` - Video streaming successfully
|
||||
- `206 Partial Content` - Range request successful
|
||||
- `404 Not Found` - Video not found or not streamable
|
||||
- `416 Range Not Satisfiable` - Invalid range request
|
||||
- `500 Internal Server Error` - Server error reading video
|
||||
|
||||
## 🔐 Security Notes
|
||||
|
||||
### Current Configuration
|
||||
- **Authentication**: None (open access)
|
||||
- **CORS**: Enabled for all origins
|
||||
- **Network**: Designed for internal use
|
||||
- **HTTPS**: Not required (HTTP works)
|
||||
|
||||
### For Production Use
|
||||
Consider implementing:
|
||||
- Authentication/authorization
|
||||
- Rate limiting
|
||||
- HTTPS/TLS encryption
|
||||
- Network access controls
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Quick Test
|
||||
```bash
|
||||
# Test video listing
|
||||
curl "http://localhost:8000/videos/?limit=5"
|
||||
|
||||
# Test video streaming
|
||||
curl -I "http://localhost:8000/videos/camera1_auto_blower_separator_20250805_123329.mp4/stream"
|
||||
|
||||
# Test range request
|
||||
curl -H "Range: bytes=0-1023" "http://localhost:8000/videos/camera1_auto_blower_separator_20250805_123329.mp4/stream" -o test_chunk.mp4
|
||||
```
|
||||
|
||||
### Browser Test
|
||||
Open: `file:///home/alireza/USDA-vision-cameras/test_video_streaming.html`
|
||||
|
||||
## 📞 Support
|
||||
|
||||
### Service Management
|
||||
```bash
|
||||
# Restart video service
|
||||
sudo systemctl restart usda-vision-camera
|
||||
|
||||
# Check service status
|
||||
sudo systemctl status usda-vision-camera
|
||||
|
||||
# View logs
|
||||
sudo journalctl -u usda-vision-camera -f
|
||||
```
|
||||
|
||||
### Health Check
|
||||
```bash
|
||||
curl http://localhost:8000/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**✅ Ready for Integration**: The video streaming system is fully operational and ready for web application integration. All MP4 files are streamable with progressive playback support.
|
||||
521
camera-management-api/docs/api/CAMERA_CONFIG_API.md
Normal file
521
camera-management-api/docs/api/CAMERA_CONFIG_API.md
Normal file
@@ -0,0 +1,521 @@
|
||||
# 🎛️ Camera Configuration API Guide
|
||||
|
||||
This guide explains how to configure camera settings via API endpoints, including all the advanced settings from your config.json.
|
||||
|
||||
> **Note**: This document is part of the comprehensive [USDA Vision Camera System API Documentation](../API_DOCUMENTATION.md). For complete API reference, see the main documentation.
|
||||
|
||||
## 📋 Configuration Categories
|
||||
|
||||
### ✅ **Real-time Configurable (No Restart Required)**
|
||||
These settings can be changed while the camera is active:
|
||||
|
||||
- **Basic**: `exposure_ms`, `gain`, `target_fps`
|
||||
- **Image Quality**: `sharpness`, `contrast`, `saturation`, `gamma`
|
||||
- **Color**: `auto_white_balance`, `color_temperature_preset`
|
||||
- **White Balance**: `wb_red_gain`, `wb_green_gain`, `wb_blue_gain`
|
||||
- **Advanced**: `anti_flicker_enabled`, `light_frequency`
|
||||
- **HDR**: `hdr_enabled`, `hdr_gain_mode`
|
||||
|
||||
### ⚠️ **Restart Required**
|
||||
These settings require camera restart to take effect:
|
||||
|
||||
- **Noise Reduction**: `noise_filter_enabled`, `denoise_3d_enabled`
|
||||
- **Video Recording**: `video_format`, `video_codec`, `video_quality`
|
||||
- **System**: `machine_topic`, `storage_path`, `enabled`, `bit_depth`
|
||||
|
||||
### 🔒 **Read-Only Fields**
|
||||
These fields are returned in the response but cannot be modified via the API:
|
||||
|
||||
- **System Info**: `name`, `machine_topic`, `storage_path`, `enabled`
|
||||
- **Auto-Recording**: `auto_start_recording_enabled`, `auto_recording_max_retries`, `auto_recording_retry_delay_seconds`
|
||||
|
||||
## 🔌 API Endpoints
|
||||
|
||||
### 1. Get Camera Configuration
|
||||
```http
|
||||
GET /cameras/{camera_name}/config
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "blower_separator",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 0.3,
|
||||
"gain": 4.0,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"video_format": "mp4",
|
||||
"video_codec": "mp4v",
|
||||
"video_quality": 95,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
"contrast": 100,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 0,
|
||||
"wb_red_gain": 0.94,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.87,
|
||||
"anti_flicker_enabled": false,
|
||||
"light_frequency": 0,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 2
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Update Camera Configuration
|
||||
```http
|
||||
PUT /cameras/{camera_name}/config
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body (all fields optional):**
|
||||
```json
|
||||
{
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"target_fps": 10.0,
|
||||
"sharpness": 150,
|
||||
"contrast": 120,
|
||||
"saturation": 110,
|
||||
"gamma": 90,
|
||||
"noise_filter_enabled": true,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 1,
|
||||
"wb_red_gain": 1.2,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.8,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Camera camera1 configuration updated",
|
||||
"updated_settings": ["exposure_ms", "gain", "sharpness", "wb_red_gain"]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Apply Configuration (Restart Camera)
|
||||
```http
|
||||
POST /cameras/{camera_name}/apply-config
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Configuration applied to camera camera1"
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Setting Ranges and Descriptions
|
||||
|
||||
### System Settings
|
||||
| Setting | Values | Default | Description |
|
||||
|---------|--------|---------|-------------|
|
||||
| `name` | string | - | Camera identifier (read-only) |
|
||||
| `machine_topic` | string | - | MQTT topic for machine state (read-only) |
|
||||
| `storage_path` | string | - | Video storage directory (read-only) |
|
||||
| `enabled` | true/false | true | Camera enabled status (read-only) |
|
||||
|
||||
### Auto-Recording Settings
|
||||
| Setting | Range | Default | Description |
|
||||
|---------|-------|---------|-------------|
|
||||
| `auto_start_recording_enabled` | true/false | true | Enable automatic recording on machine state changes (read-only) |
|
||||
| `auto_recording_max_retries` | 1-10 | 3 | Maximum retry attempts for failed recordings (read-only) |
|
||||
| `auto_recording_retry_delay_seconds` | 1-30 | 2 | Delay between retry attempts in seconds (read-only) |
|
||||
|
||||
### Basic Settings
|
||||
| Setting | Range | Default | Description |
|
||||
|---------|-------|---------|-------------|
|
||||
| `exposure_ms` | 0.1 - 1000.0 | 1.0 | Exposure time in milliseconds |
|
||||
| `gain` | 0.0 - 20.0 | 3.5 | Camera gain multiplier |
|
||||
| `target_fps` | 0.0 - 120.0 | 0 | Target FPS (0 = maximum) |
|
||||
|
||||
### Image Quality Settings
|
||||
| Setting | Range | Default | Description |
|
||||
|---------|-------|---------|-------------|
|
||||
| `sharpness` | 0 - 200 | 100 | Image sharpness (100 = no sharpening) |
|
||||
| `contrast` | 0 - 200 | 100 | Image contrast (100 = normal) |
|
||||
| `saturation` | 0 - 200 | 100 | Color saturation (color cameras only) |
|
||||
| `gamma` | 0 - 300 | 100 | Gamma correction (100 = normal) |
|
||||
|
||||
### Color Settings
|
||||
| Setting | Values | Default | Description |
|
||||
|---------|--------|---------|-------------|
|
||||
| `auto_white_balance` | true/false | true | Automatic white balance |
|
||||
| `color_temperature_preset` | 0-10 | 0 | Color temperature preset (0=auto) |
|
||||
|
||||
### Manual White Balance RGB Gains
|
||||
| Setting | Range | Default | Description |
|
||||
|---------|-------|---------|-------------|
|
||||
| `wb_red_gain` | 0.0 - 3.99 | 1.0 | Red channel gain for manual white balance |
|
||||
| `wb_green_gain` | 0.0 - 3.99 | 1.0 | Green channel gain for manual white balance |
|
||||
| `wb_blue_gain` | 0.0 - 3.99 | 1.0 | Blue channel gain for manual white balance |
|
||||
|
||||
### Advanced Settings
|
||||
| Setting | Values | Default | Description |
|
||||
|---------|--------|---------|-------------|
|
||||
| `anti_flicker_enabled` | true/false | true | Reduce artificial lighting flicker |
|
||||
| `light_frequency` | 0/1 | 1 | Light frequency (0=50Hz, 1=60Hz) |
|
||||
| `noise_filter_enabled` | true/false | true | Basic noise filtering |
|
||||
| `denoise_3d_enabled` | true/false | false | Advanced 3D denoising |
|
||||
|
||||
### HDR Settings
|
||||
| Setting | Values | Default | Description |
|
||||
|---------|--------|---------|-------------|
|
||||
| `hdr_enabled` | true/false | false | High Dynamic Range |
|
||||
| `hdr_gain_mode` | 0-3 | 0 | HDR processing mode |
|
||||
|
||||
## 🚀 Usage Examples
|
||||
|
||||
### Example 1: Adjust Exposure and Gain
|
||||
```bash
|
||||
curl -X PUT http://localhost:8000/cameras/camera1/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"exposure_ms": 1.5,
|
||||
"gain": 4.0
|
||||
}'
|
||||
```
|
||||
|
||||
### Example 2: Improve Image Quality
|
||||
```bash
|
||||
curl -X PUT http://localhost:8000/cameras/camera1/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"sharpness": 150,
|
||||
"contrast": 120,
|
||||
"gamma": 90
|
||||
}'
|
||||
```
|
||||
|
||||
### Example 3: Configure for Indoor Lighting
|
||||
```bash
|
||||
curl -X PUT http://localhost:8000/cameras/camera1/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 2
|
||||
}'
|
||||
```
|
||||
|
||||
### Example 4: Enable HDR Mode
|
||||
```bash
|
||||
curl -X PUT http://localhost:8000/cameras/camera1/config \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"hdr_enabled": true,
|
||||
"hdr_gain_mode": 1
|
||||
}'
|
||||
```
|
||||
|
||||
## ⚛️ React Integration Examples
|
||||
|
||||
### Camera Configuration Component
|
||||
```jsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
const CameraConfig = ({ cameraName, apiBaseUrl = 'http://localhost:8000' }) => {
|
||||
const [config, setConfig] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
// Load current configuration
|
||||
useEffect(() => {
|
||||
fetchConfig();
|
||||
}, [cameraName]);
|
||||
|
||||
const fetchConfig = async () => {
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/config`);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setConfig(data);
|
||||
} else {
|
||||
setError('Failed to load configuration');
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Error: ${err.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
const updateConfig = async (updates) => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/config`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(updates)
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
console.log('Updated settings:', result.updated_settings);
|
||||
await fetchConfig(); // Reload configuration
|
||||
} else {
|
||||
const error = await response.json();
|
||||
setError(error.detail || 'Update failed');
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Error: ${err.message}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSliderChange = (setting, value) => {
|
||||
updateConfig({ [setting]: value });
|
||||
};
|
||||
|
||||
if (!config) return <div>Loading configuration...</div>;
|
||||
|
||||
return (
|
||||
<div className="camera-config">
|
||||
<h3>Camera Configuration: {cameraName}</h3>
|
||||
|
||||
{/* System Information (Read-Only) */}
|
||||
<div className="config-section">
|
||||
<h4>System Information</h4>
|
||||
<div className="info-grid">
|
||||
<div><strong>Name:</strong> {config.name}</div>
|
||||
<div><strong>Machine Topic:</strong> {config.machine_topic}</div>
|
||||
<div><strong>Storage Path:</strong> {config.storage_path}</div>
|
||||
<div><strong>Enabled:</strong> {config.enabled ? 'Yes' : 'No'}</div>
|
||||
<div><strong>Auto Recording:</strong> {config.auto_start_recording_enabled ? 'Enabled' : 'Disabled'}</div>
|
||||
<div><strong>Max Retries:</strong> {config.auto_recording_max_retries}</div>
|
||||
<div><strong>Retry Delay:</strong> {config.auto_recording_retry_delay_seconds}s</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Basic Settings */}
|
||||
<div className="config-section">
|
||||
<h4>Basic Settings</h4>
|
||||
|
||||
<div className="setting">
|
||||
<label>Exposure (ms): {config.exposure_ms}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0.1"
|
||||
max="10"
|
||||
step="0.1"
|
||||
value={config.exposure_ms}
|
||||
onChange={(e) => handleSliderChange('exposure_ms', parseFloat(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>Gain: {config.gain}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="10"
|
||||
step="0.1"
|
||||
value={config.gain}
|
||||
onChange={(e) => handleSliderChange('gain', parseFloat(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>Target FPS: {config.target_fps}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="30"
|
||||
step="1"
|
||||
value={config.target_fps}
|
||||
onChange={(e) => handleSliderChange('target_fps', parseInt(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Image Quality Settings */}
|
||||
<div className="config-section">
|
||||
<h4>Image Quality</h4>
|
||||
|
||||
<div className="setting">
|
||||
<label>Sharpness: {config.sharpness}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="200"
|
||||
value={config.sharpness}
|
||||
onChange={(e) => handleSliderChange('sharpness', parseInt(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>Contrast: {config.contrast}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="200"
|
||||
value={config.contrast}
|
||||
onChange={(e) => handleSliderChange('contrast', parseInt(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>Gamma: {config.gamma}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="300"
|
||||
value={config.gamma}
|
||||
onChange={(e) => handleSliderChange('gamma', parseInt(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* White Balance RGB Gains */}
|
||||
<div className="config-section">
|
||||
<h4>White Balance RGB Gains</h4>
|
||||
|
||||
<div className="setting">
|
||||
<label>Red Gain: {config.wb_red_gain}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="3.99"
|
||||
step="0.01"
|
||||
value={config.wb_red_gain}
|
||||
onChange={(e) => handleSliderChange('wb_red_gain', parseFloat(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>Green Gain: {config.wb_green_gain}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="3.99"
|
||||
step="0.01"
|
||||
value={config.wb_green_gain}
|
||||
onChange={(e) => handleSliderChange('wb_green_gain', parseFloat(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>Blue Gain: {config.wb_blue_gain}</label>
|
||||
<input
|
||||
type="range"
|
||||
min="0"
|
||||
max="3.99"
|
||||
step="0.01"
|
||||
value={config.wb_blue_gain}
|
||||
onChange={(e) => handleSliderChange('wb_blue_gain', parseFloat(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Advanced Settings */}
|
||||
<div className="config-section">
|
||||
<h4>Advanced Settings</h4>
|
||||
|
||||
<div className="setting">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={config.anti_flicker_enabled}
|
||||
onChange={(e) => updateConfig({ anti_flicker_enabled: e.target.checked })}
|
||||
/>
|
||||
Anti-flicker Enabled
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={config.auto_white_balance}
|
||||
onChange={(e) => updateConfig({ auto_white_balance: e.target.checked })}
|
||||
/>
|
||||
Auto White Balance
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="setting">
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={config.hdr_enabled}
|
||||
onChange={(e) => updateConfig({ hdr_enabled: e.target.checked })}
|
||||
/>
|
||||
HDR Enabled
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="error" style={{ color: 'red', marginTop: '10px' }}>
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{loading && <div>Updating configuration...</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CameraConfig;
|
||||
```
|
||||
|
||||
## 🔄 Configuration Workflow
|
||||
|
||||
### 1. Real-time Adjustments
|
||||
For settings that don't require restart:
|
||||
```bash
|
||||
# Update settings
|
||||
curl -X PUT /cameras/camera1/config -d '{"exposure_ms": 2.0}'
|
||||
|
||||
# Settings take effect immediately
|
||||
# Continue recording/streaming without interruption
|
||||
```
|
||||
|
||||
### 2. Settings Requiring Restart
|
||||
For noise reduction and system settings:
|
||||
```bash
|
||||
# Update settings
|
||||
curl -X PUT /cameras/camera1/config -d '{"noise_filter_enabled": false}'
|
||||
|
||||
# Apply configuration (restarts camera)
|
||||
curl -X POST /cameras/camera1/apply-config
|
||||
|
||||
# Camera reinitializes with new settings
|
||||
```
|
||||
|
||||
## 🚨 Important Notes
|
||||
|
||||
### Camera State During Updates
|
||||
- **Real-time settings**: Applied immediately, no interruption
|
||||
- **Restart-required settings**: Saved to config, applied on next restart
|
||||
- **Recording**: Continues during real-time updates
|
||||
- **Streaming**: Continues during real-time updates
|
||||
|
||||
### Error Handling
|
||||
- Invalid ranges return HTTP 422 with validation errors
|
||||
- Camera not found returns HTTP 404
|
||||
- SDK errors are logged and return HTTP 500
|
||||
|
||||
### Performance Impact
|
||||
- **Image quality settings**: Minimal performance impact
|
||||
- **Noise reduction**: May reduce FPS when enabled
|
||||
- **HDR**: Significant processing overhead when enabled
|
||||
|
||||
This comprehensive API allows you to control all camera settings programmatically, making it perfect for integration with React dashboards or automated optimization systems!
|
||||
127
camera-management-api/docs/camera/BLOWER_CAMERA_CONFIG.md
Normal file
127
camera-management-api/docs/camera/BLOWER_CAMERA_CONFIG.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# Blower Camera (Camera1) Configuration
|
||||
|
||||
This document describes the default configuration for the blower camera (Camera1) based on the GigE camera settings from the dedicated software.
|
||||
|
||||
## Camera Identification
|
||||
- **Camera Name**: camera1 (Blower-Yield-Cam)
|
||||
- **Machine Topic**: blower_separator
|
||||
- **Purpose**: Monitors the blower separator machine
|
||||
|
||||
## Configuration Summary
|
||||
|
||||
Based on the camera settings screenshots, the following configuration has been applied to Camera1:
|
||||
|
||||
### Exposure Settings
|
||||
- **Mode**: Manual (not Auto)
|
||||
- **Exposure Time**: 1.0ms (1000μs)
|
||||
- **Gain**: 3.5x (350 in camera units)
|
||||
- **Anti-Flicker**: Enabled (50Hz mode)
|
||||
|
||||
### Color Processing Settings
|
||||
- **White Balance Mode**: Manual (not Auto)
|
||||
- **Color Temperature**: D65 (6500K)
|
||||
- **RGB Gain Values**:
|
||||
- Red Gain: 1.00
|
||||
- Green Gain: 1.00
|
||||
- Blue Gain: 1.00
|
||||
- **Saturation**: 100 (normal)
|
||||
|
||||
### LUT (Look-Up Table) Settings
|
||||
- **Mode**: Dynamically generated (not Preset or Custom)
|
||||
- **Gamma**: 1.00 (100 in config units)
|
||||
- **Contrast**: 100 (normal)
|
||||
|
||||
### Advanced Settings
|
||||
- **Anti-Flicker**: Enabled
|
||||
- **Light Frequency**: 60Hz (1 in config)
|
||||
- **Bit Depth**: 8-bit
|
||||
- **HDR**: Disabled
|
||||
|
||||
## Configuration Mapping
|
||||
|
||||
The screenshots show these key settings that have been mapped to the config.json:
|
||||
|
||||
| Screenshot Setting | Config Parameter | Value | Notes |
|
||||
|-------------------|------------------|-------|-------|
|
||||
| Manual Exposure | auto_exposure | false | Exposure mode set to manual |
|
||||
| Time(ms): 1.0000 | exposure_ms | 1.0 | Exposure time in milliseconds |
|
||||
| Gain(multiple): 3.500 | gain | 3.5 | Analog gain multiplier |
|
||||
| Manual White Balance | auto_white_balance | false | Manual WB mode |
|
||||
| Color Temperature: D65 | color_temperature_preset | 6500 | D65 = 6500K |
|
||||
| Red Gain: 1.00 | wb_red_gain | 1.0 | Manual RGB gain |
|
||||
| Green Gain: 1.00 | wb_green_gain | 1.0 | Manual RGB gain |
|
||||
| Blue Gain: 1.00 | wb_blue_gain | 1.0 | Manual RGB gain |
|
||||
| Saturation: 100 | saturation | 100 | Color saturation |
|
||||
| Gamma: 1.00 | gamma | 100 | Gamma correction |
|
||||
| Contrast: 100 | contrast | 100 | Image contrast |
|
||||
| 50HZ Anti-Flicker | anti_flicker_enabled | true | Flicker reduction |
|
||||
| 60Hz frequency | light_frequency | 1 | Power frequency |
|
||||
|
||||
## Current Configuration
|
||||
|
||||
The current config.json for camera1 includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "blower_separator",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.5,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
"sharpness": 100,
|
||||
"contrast": 100,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 6500,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
```
|
||||
|
||||
## Camera Preview Enhancement
|
||||
|
||||
**Important Update**: The camera preview/streaming functionality has been enhanced to apply all default configuration settings from config.json, ensuring that preview images match the quality and appearance of recorded videos.
|
||||
|
||||
### What This Means for Camera1
|
||||
|
||||
When you view the camera preview, you'll now see:
|
||||
- **Manual exposure** (1.0ms) and **high gain** (3.5x) applied
|
||||
- **50Hz anti-flicker** filtering active
|
||||
- **Manual white balance** with balanced RGB gains (1.0, 1.0, 1.0)
|
||||
- **Standard image processing** (sharpness: 100, contrast: 100, gamma: 100, saturation: 100)
|
||||
- **D65 color temperature** (6500K) applied
|
||||
|
||||
This ensures the preview accurately represents what will be recorded.
|
||||
|
||||
## Notes
|
||||
|
||||
1. **Machine Topic Correction**: The machine topic has been corrected from "vibratory_conveyor" to "blower_separator" to match the camera's actual monitoring purpose.
|
||||
|
||||
2. **Manual White Balance**: The camera is configured for manual white balance with D65 color temperature, which is appropriate for daylight conditions.
|
||||
|
||||
3. **RGB Gain Support**: The current configuration system needs to be extended to support individual RGB gain values for manual white balance fine-tuning.
|
||||
|
||||
4. **Anti-Flicker**: Enabled to reduce artificial lighting interference, set to 60Hz to match North American power frequency.
|
||||
|
||||
5. **LUT Mode**: The camera uses dynamically generated LUT with gamma=1.00 and contrast=100, which provides linear response.
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
To fully support all settings shown in the screenshots, the following parameters should be added to the configuration system:
|
||||
|
||||
- `wb_red_gain`: Red channel gain for manual white balance (0.0-3.99)
|
||||
- `wb_green_gain`: Green channel gain for manual white balance (0.0-3.99)
|
||||
- `wb_blue_gain`: Blue channel gain for manual white balance (0.0-3.99)
|
||||
- `lut_mode`: LUT generation mode (0=dynamic, 1=preset, 2=custom)
|
||||
- `lut_preset`: Preset LUT selection when using preset mode
|
||||
150
camera-management-api/docs/camera/CONVEYOR_CAMERA_CONFIG.md
Normal file
150
camera-management-api/docs/camera/CONVEYOR_CAMERA_CONFIG.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Conveyor Camera (Camera2) Configuration
|
||||
|
||||
This document describes the default configuration for the conveyor camera (Camera2) based on the GigE camera settings from the dedicated software.
|
||||
|
||||
## Camera Identification
|
||||
- **Camera Name**: camera2 (Cracker-Cam)
|
||||
- **Machine Topic**: vibratory_conveyor
|
||||
- **Purpose**: Monitors the vibratory conveyor/cracker machine
|
||||
|
||||
## Configuration Summary
|
||||
|
||||
Based on the camera settings screenshots, the following configuration has been applied to Camera2:
|
||||
|
||||
### Color Processing Settings
|
||||
- **White Balance Mode**: Manual (not Auto)
|
||||
- **Color Temperature**: D65 (6500K)
|
||||
- **RGB Gain Values**:
|
||||
- Red Gain: 1.01
|
||||
- Green Gain: 1.00
|
||||
- Blue Gain: 0.87
|
||||
- **Saturation**: 100 (normal)
|
||||
|
||||
### LUT (Look-Up Table) Settings
|
||||
- **Mode**: Dynamically generated (not Preset or Custom)
|
||||
- **Gamma**: 1.00 (100 in config units)
|
||||
- **Contrast**: 100 (normal)
|
||||
|
||||
### Graphic Processing Settings
|
||||
- **Sharpness Level**: 0 (no sharpening applied)
|
||||
- **Noise Reduction**:
|
||||
- Denoise2D: Disabled
|
||||
- Denoise3D: Disabled
|
||||
- **Rotation**: Disabled
|
||||
- **Lens Distortion Correction**: Disabled
|
||||
- **Dead Pixel Correction**: Enabled
|
||||
- **Flat Fielding Correction**: Disabled
|
||||
|
||||
## Configuration Mapping
|
||||
|
||||
The screenshots show these key settings that have been mapped to the config.json:
|
||||
|
||||
| Screenshot Setting | Config Parameter | Value | Notes |
|
||||
|-------------------|------------------|-------|-------|
|
||||
| Manual White Balance | auto_white_balance | false | Manual WB mode |
|
||||
| Color Temperature: D65 | color_temperature_preset | 6500 | D65 = 6500K |
|
||||
| Red Gain: 1.01 | wb_red_gain | 1.01 | Manual RGB gain |
|
||||
| Green Gain: 1.00 | wb_green_gain | 1.0 | Manual RGB gain |
|
||||
| Blue Gain: 0.87 | wb_blue_gain | 0.87 | Manual RGB gain |
|
||||
| Saturation: 100 | saturation | 100 | Color saturation |
|
||||
| Gamma: 1.00 | gamma | 100 | Gamma correction |
|
||||
| Contrast: 100 | contrast | 100 | Image contrast |
|
||||
| Sharpen Level: 0 | sharpness | 0 | No sharpening |
|
||||
| Denoise2D: Disabled | noise_filter_enabled | false | Basic noise filter off |
|
||||
| Denoise3D: Disable | denoise_3d_enabled | false | Advanced denoising off |
|
||||
|
||||
## Current Configuration
|
||||
|
||||
The current config.json for camera2 includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "camera2",
|
||||
"machine_topic": "vibratory_conveyor",
|
||||
"storage_path": "/storage/camera2",
|
||||
"exposure_ms": 0.5,
|
||||
"gain": 0.3,
|
||||
"target_fps": 0,
|
||||
"enabled": true,
|
||||
"auto_start_recording_enabled": true,
|
||||
"auto_recording_max_retries": 3,
|
||||
"auto_recording_retry_delay_seconds": 2,
|
||||
"sharpness": 0,
|
||||
"contrast": 100,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 6500,
|
||||
"wb_red_gain": 1.01,
|
||||
"wb_green_gain": 1.0,
|
||||
"wb_blue_gain": 0.87,
|
||||
"anti_flicker_enabled": false,
|
||||
"light_frequency": 1,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
```
|
||||
|
||||
## Key Differences from Camera1 (Blower Camera)
|
||||
|
||||
1. **RGB Gain Tuning**: Camera2 has custom RGB gains (R:1.01, G:1.00, B:0.87) vs Camera1's balanced gains (all 1.0)
|
||||
2. **Sharpness**: Camera2 has sharpness disabled (0) vs Camera1's normal sharpness (100)
|
||||
3. **Exposure/Gain**: Camera2 uses lower exposure (0.5ms) and gain (0.3x) vs Camera1's higher values (1.0ms, 3.5x)
|
||||
4. **Anti-Flicker**: Camera2 has anti-flicker disabled vs Camera1's enabled anti-flicker
|
||||
|
||||
## Notes
|
||||
|
||||
1. **Custom White Balance**: Camera2 uses manual white balance with custom RGB gains, suggesting specific lighting conditions or color correction requirements for the conveyor monitoring.
|
||||
|
||||
2. **No Sharpening**: Sharpness is set to 0, indicating the raw image quality is preferred without artificial enhancement.
|
||||
|
||||
3. **Minimal Noise Reduction**: Both 2D and 3D denoising are disabled, prioritizing image authenticity over noise reduction.
|
||||
|
||||
4. **Dead Pixel Correction**: Enabled to handle any defective pixels on the sensor.
|
||||
|
||||
5. **Lower Sensitivity**: The lower exposure and gain settings suggest better lighting conditions or different monitoring requirements compared to the blower camera.
|
||||
|
||||
## Camera Preview Enhancement
|
||||
|
||||
**Important Update**: The camera preview/streaming functionality has been enhanced to apply all default configuration settings from config.json, ensuring that preview images match the quality and appearance of recorded videos.
|
||||
|
||||
### What Changed
|
||||
|
||||
Previously, camera preview only applied basic settings (exposure, gain, trigger mode). Now, the preview applies the complete configuration including:
|
||||
|
||||
- **Image Quality**: Sharpness, contrast, gamma, saturation
|
||||
- **Color Processing**: White balance mode, color temperature, RGB gains
|
||||
- **Advanced Settings**: Anti-flicker, light frequency, HDR settings
|
||||
- **Noise Reduction**: Filter and 3D denoising settings (where supported)
|
||||
|
||||
### Benefits
|
||||
|
||||
1. **WYSIWYG Preview**: What you see in the preview is exactly what gets recorded
|
||||
2. **Accurate Color Representation**: Manual white balance and RGB gains are applied to preview
|
||||
3. **Consistent Image Quality**: Sharpness, contrast, and gamma settings match recording
|
||||
4. **Proper Exposure**: Anti-flicker and lighting frequency settings are applied
|
||||
|
||||
### Technical Implementation
|
||||
|
||||
The `CameraStreamer` class now includes the same comprehensive configuration methods as `CameraRecorder`:
|
||||
|
||||
- `_configure_image_quality()`: Applies sharpness, contrast, gamma, saturation
|
||||
- `_configure_color_settings()`: Applies white balance mode, color temperature, RGB gains
|
||||
- `_configure_advanced_settings()`: Applies anti-flicker, light frequency, HDR
|
||||
- `_configure_noise_reduction()`: Applies noise filter settings
|
||||
|
||||
These methods are called during camera initialization for streaming, ensuring all config.json settings are applied.
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Additional parameters that could be added to support all graphic processing features:
|
||||
|
||||
- `rotation_angle`: Image rotation (0, 90, 180, 270 degrees)
|
||||
- `lens_distortion_correction`: Enable/disable lens distortion correction
|
||||
- `dead_pixel_correction`: Enable/disable dead pixel correction
|
||||
- `flat_fielding_correction`: Enable/disable flat fielding correction
|
||||
- `mirror_horizontal`: Horizontal mirroring
|
||||
- `mirror_vertical`: Vertical mirroring
|
||||
159
camera-management-api/docs/camera/PREVIEW_ENHANCEMENT.md
Normal file
159
camera-management-api/docs/camera/PREVIEW_ENHANCEMENT.md
Normal file
@@ -0,0 +1,159 @@
|
||||
# Camera Preview Enhancement
|
||||
|
||||
## Overview
|
||||
|
||||
The camera preview/streaming functionality has been significantly enhanced to apply all default configuration settings from `config.json`, ensuring that preview images accurately represent what will be recorded.
|
||||
|
||||
## Problem Solved
|
||||
|
||||
Previously, camera preview only applied basic settings (exposure, gain, trigger mode, frame rate), while recording applied the full configuration. This meant:
|
||||
|
||||
- Preview images looked different from recorded videos
|
||||
- Color balance, sharpness, and other image quality settings were not visible in preview
|
||||
- Users couldn't accurately assess the final recording quality from the preview
|
||||
|
||||
## Solution Implemented
|
||||
|
||||
The `CameraStreamer` class has been enhanced with comprehensive configuration methods that mirror those in `CameraRecorder`:
|
||||
|
||||
### New Configuration Methods Added
|
||||
|
||||
1. **`_configure_image_quality()`**
|
||||
- Applies sharpness settings (0-200)
|
||||
- Applies contrast settings (0-200)
|
||||
- Applies gamma correction (0-300)
|
||||
- Applies saturation for color cameras (0-200)
|
||||
|
||||
2. **`_configure_color_settings()`**
|
||||
- Sets white balance mode (auto/manual)
|
||||
- Applies color temperature presets
|
||||
- Sets manual RGB gains for precise color tuning
|
||||
|
||||
3. **`_configure_advanced_settings()`**
|
||||
- Enables/disables anti-flicker filtering
|
||||
- Sets light frequency (50Hz/60Hz)
|
||||
- Configures HDR settings when available
|
||||
|
||||
4. **`_configure_noise_reduction()`**
|
||||
- Configures noise filter settings
|
||||
- Configures 3D denoising settings
|
||||
|
||||
### Enhanced Main Configuration Method
|
||||
|
||||
The `_configure_streaming_settings()` method now calls all configuration methods:
|
||||
|
||||
```python
|
||||
def _configure_streaming_settings(self):
|
||||
"""Configure camera settings from config.json for streaming"""
|
||||
try:
|
||||
# Basic settings (existing)
|
||||
mvsdk.CameraSetTriggerMode(self.hCamera, 0)
|
||||
mvsdk.CameraSetAeState(self.hCamera, 0)
|
||||
exposure_us = int(self.camera_config.exposure_ms * 1000)
|
||||
mvsdk.CameraSetExposureTime(self.hCamera, exposure_us)
|
||||
gain_value = int(self.camera_config.gain * 100)
|
||||
mvsdk.CameraSetAnalogGain(self.hCamera, gain_value)
|
||||
|
||||
# Comprehensive configuration (new)
|
||||
self._configure_image_quality()
|
||||
self._configure_noise_reduction()
|
||||
if not self.monoCamera:
|
||||
self._configure_color_settings()
|
||||
self._configure_advanced_settings()
|
||||
|
||||
except Exception as e:
|
||||
self.logger.warning(f"Could not configure some streaming settings: {e}")
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
### 1. WYSIWYG Preview
|
||||
- **What You See Is What You Get**: Preview now accurately represents final recording quality
|
||||
- **Real-time Assessment**: Users can evaluate recording quality before starting actual recording
|
||||
- **Consistent Experience**: No surprises when comparing preview to recorded footage
|
||||
|
||||
### 2. Accurate Color Representation
|
||||
- **Manual White Balance**: RGB gains are applied to preview for accurate color reproduction
|
||||
- **Color Temperature**: D65 or other presets are applied consistently
|
||||
- **Saturation**: Color intensity matches recording settings
|
||||
|
||||
### 3. Proper Image Quality
|
||||
- **Sharpness**: Edge enhancement settings are visible in preview
|
||||
- **Contrast**: Dynamic range adjustments are applied
|
||||
- **Gamma**: Brightness curve corrections are active
|
||||
|
||||
### 4. Environmental Adaptation
|
||||
- **Anti-Flicker**: Artificial lighting interference is filtered in preview
|
||||
- **Light Frequency**: 50Hz/60Hz settings match local power grid
|
||||
- **HDR**: High dynamic range processing when enabled
|
||||
|
||||
## Camera-Specific Impact
|
||||
|
||||
### Camera1 (Blower Separator)
|
||||
Preview now shows:
|
||||
- Manual exposure (1.0ms) and high gain (3.5x)
|
||||
- 50Hz anti-flicker filtering
|
||||
- Manual white balance with balanced RGB gains (1.0, 1.0, 1.0)
|
||||
- Standard image processing (sharpness: 100, contrast: 100, gamma: 100, saturation: 100)
|
||||
- D65 color temperature (6500K)
|
||||
|
||||
### Camera2 (Conveyor/Cracker)
|
||||
Preview now shows:
|
||||
- Manual exposure (0.5ms) and lower gain (0.3x)
|
||||
- Custom RGB color tuning (R:1.01, G:1.00, B:0.87)
|
||||
- No image sharpening (sharpness: 0)
|
||||
- Enhanced saturation (100) and proper gamma (100)
|
||||
- D65 color temperature with manual white balance
|
||||
|
||||
## Technical Implementation Details
|
||||
|
||||
### Error Handling
|
||||
- All configuration methods include try-catch blocks
|
||||
- Warnings are logged for unsupported features
|
||||
- Graceful degradation when SDK functions are unavailable
|
||||
- Streaming continues even if some settings fail to apply
|
||||
|
||||
### SDK Compatibility
|
||||
- Checks for function availability before calling
|
||||
- Handles different SDK versions gracefully
|
||||
- Logs informational messages for unavailable features
|
||||
|
||||
### Performance Considerations
|
||||
- Configuration is applied once during camera initialization
|
||||
- No performance impact on streaming frame rate
|
||||
- Separate camera instance for streaming (doesn't interfere with recording)
|
||||
|
||||
## Usage
|
||||
|
||||
No changes required for users - the enhancement is automatic:
|
||||
|
||||
1. **Start Preview**: Use existing preview endpoints
|
||||
2. **View Stream**: Camera automatically applies all config.json settings
|
||||
3. **Compare**: Preview now matches recording quality exactly
|
||||
|
||||
### API Endpoints (unchanged)
|
||||
- `GET /cameras/{camera_name}/stream` - Get live MJPEG stream
|
||||
- `POST /cameras/{camera_name}/start-stream` - Start streaming
|
||||
- `POST /cameras/{camera_name}/stop-stream` - Stop streaming
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Additional settings that could be added to further improve preview accuracy:
|
||||
|
||||
1. **Geometric Corrections**
|
||||
- Lens distortion correction
|
||||
- Dead pixel correction
|
||||
- Flat fielding correction
|
||||
|
||||
2. **Image Transformations**
|
||||
- Rotation (90°, 180°, 270°)
|
||||
- Horizontal/vertical mirroring
|
||||
|
||||
3. **Advanced Processing**
|
||||
- Custom LUT (Look-Up Table) support
|
||||
- Advanced noise reduction algorithms
|
||||
- Real-time image enhancement filters
|
||||
|
||||
## Conclusion
|
||||
|
||||
This enhancement significantly improves the user experience by providing accurate, real-time preview of camera output with all configuration settings applied. Users can now confidently assess recording quality, adjust settings, and ensure optimal camera performance before starting critical recordings.
|
||||
@@ -0,0 +1,262 @@
|
||||
# Auto-Recording Feature Implementation Guide
|
||||
|
||||
## 🎯 Overview for React App Development
|
||||
|
||||
This document provides a comprehensive guide for updating the React application to support the new auto-recording feature that was added to the USDA Vision Camera System.
|
||||
|
||||
> **📚 For complete API reference**: See the [USDA Vision Camera System API Documentation](../API_DOCUMENTATION.md) for detailed endpoint specifications and examples.
|
||||
|
||||
## 📋 What Changed in the Backend
|
||||
|
||||
### New API Endpoints Added
|
||||
|
||||
1. **Enable Auto-Recording**
|
||||
```http
|
||||
POST /cameras/{camera_name}/auto-recording/enable
|
||||
Response: AutoRecordingConfigResponse
|
||||
```
|
||||
|
||||
2. **Disable Auto-Recording**
|
||||
```http
|
||||
POST /cameras/{camera_name}/auto-recording/disable
|
||||
Response: AutoRecordingConfigResponse
|
||||
```
|
||||
|
||||
3. **Get Auto-Recording Status**
|
||||
```http
|
||||
GET /auto-recording/status
|
||||
Response: AutoRecordingStatusResponse
|
||||
```
|
||||
|
||||
### Updated API Responses
|
||||
|
||||
#### CameraStatusResponse (Updated)
|
||||
```typescript
|
||||
interface CameraStatusResponse {
|
||||
name: string;
|
||||
status: string;
|
||||
is_recording: boolean;
|
||||
last_checked: string;
|
||||
last_error?: string;
|
||||
device_info?: any;
|
||||
current_recording_file?: string;
|
||||
recording_start_time?: string;
|
||||
|
||||
// NEW AUTO-RECORDING FIELDS
|
||||
auto_recording_enabled: boolean;
|
||||
auto_recording_active: boolean;
|
||||
auto_recording_failure_count: number;
|
||||
auto_recording_last_attempt?: string;
|
||||
auto_recording_last_error?: string;
|
||||
}
|
||||
```
|
||||
|
||||
#### CameraConfigResponse (Updated)
|
||||
```typescript
|
||||
interface CameraConfigResponse {
|
||||
name: string;
|
||||
machine_topic: string;
|
||||
storage_path: string;
|
||||
enabled: boolean;
|
||||
|
||||
// NEW AUTO-RECORDING CONFIG FIELDS
|
||||
auto_start_recording_enabled: boolean;
|
||||
auto_recording_max_retries: number;
|
||||
auto_recording_retry_delay_seconds: number;
|
||||
|
||||
// ... existing fields (exposure_ms, gain, etc.)
|
||||
}
|
||||
```
|
||||
|
||||
#### New Response Types
|
||||
```typescript
|
||||
interface AutoRecordingConfigResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
camera_name: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
interface AutoRecordingStatusResponse {
|
||||
running: boolean;
|
||||
auto_recording_enabled: boolean;
|
||||
retry_queue: Record<string, any>;
|
||||
enabled_cameras: string[];
|
||||
}
|
||||
```
|
||||
|
||||
## 🎨 React App UI Requirements
|
||||
|
||||
### 1. Camera Status Display Updates
|
||||
|
||||
**Add to Camera Cards/Components:**
|
||||
- Auto-recording enabled/disabled indicator
|
||||
- Auto-recording active status (when machine is ON and auto-recording)
|
||||
- Failure count display (if > 0)
|
||||
- Last auto-recording error (if any)
|
||||
- Visual distinction between manual and auto-recording
|
||||
|
||||
**Example UI Elements:**
|
||||
```jsx
|
||||
// Auto-recording status badge
|
||||
{camera.auto_recording_enabled && (
|
||||
<Badge variant={camera.auto_recording_active ? "success" : "secondary"}>
|
||||
Auto-Recording {camera.auto_recording_active ? "Active" : "Enabled"}
|
||||
</Badge>
|
||||
)}
|
||||
|
||||
// Failure indicator
|
||||
{camera.auto_recording_failure_count > 0 && (
|
||||
<Alert variant="warning">
|
||||
Auto-recording failures: {camera.auto_recording_failure_count}
|
||||
</Alert>
|
||||
)}
|
||||
```
|
||||
|
||||
### 2. Auto-Recording Controls
|
||||
|
||||
**Add Toggle Controls:**
|
||||
- Enable/Disable auto-recording per camera
|
||||
- Global auto-recording status display
|
||||
- Retry queue monitoring
|
||||
|
||||
**Example Control Component:**
|
||||
```jsx
|
||||
const AutoRecordingToggle = ({ camera, onToggle }) => {
|
||||
const handleToggle = async () => {
|
||||
const endpoint = camera.auto_recording_enabled ? 'disable' : 'enable';
|
||||
await fetch(`/cameras/${camera.name}/auto-recording/${endpoint}`, {
|
||||
method: 'POST'
|
||||
});
|
||||
onToggle();
|
||||
};
|
||||
|
||||
return (
|
||||
<Switch
|
||||
checked={camera.auto_recording_enabled}
|
||||
onChange={handleToggle}
|
||||
label="Auto-Recording"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### 3. Machine State Integration
|
||||
|
||||
**Display Machine Status:**
|
||||
- Show which machine each camera monitors
|
||||
- Display current machine state (ON/OFF)
|
||||
- Show correlation between machine state and recording status
|
||||
|
||||
**Camera-Machine Mapping:**
|
||||
- Camera 1 → Vibratory Conveyor (conveyor/cracker cam)
|
||||
- Camera 2 → Blower Separator (blower separator)
|
||||
|
||||
### 4. Auto-Recording Dashboard
|
||||
|
||||
**Create New Dashboard Section:**
|
||||
- Overall auto-recording system status
|
||||
- List of cameras with auto-recording enabled
|
||||
- Active retry queue display
|
||||
- Recent auto-recording events/logs
|
||||
|
||||
## 🔧 Implementation Steps for React App
|
||||
|
||||
### Step 1: Update TypeScript Interfaces
|
||||
```typescript
|
||||
// Update existing interfaces in your types file
|
||||
// Add new interfaces for auto-recording responses
|
||||
```
|
||||
|
||||
### Step 2: Update API Service Functions
|
||||
```typescript
|
||||
// Add new API calls
|
||||
export const enableAutoRecording = (cameraName: string) =>
|
||||
fetch(`/cameras/${cameraName}/auto-recording/enable`, { method: 'POST' });
|
||||
|
||||
export const disableAutoRecording = (cameraName: string) =>
|
||||
fetch(`/cameras/${cameraName}/auto-recording/disable`, { method: 'POST' });
|
||||
|
||||
export const getAutoRecordingStatus = () =>
|
||||
fetch('/auto-recording/status').then(res => res.json());
|
||||
```
|
||||
|
||||
### Step 3: Update Camera Components
|
||||
- Add auto-recording status indicators
|
||||
- Add enable/disable controls
|
||||
- Update recording status display to distinguish auto vs manual
|
||||
|
||||
### Step 4: Create Auto-Recording Management Panel
|
||||
- System-wide auto-recording status
|
||||
- Per-camera auto-recording controls
|
||||
- Retry queue monitoring
|
||||
- Error reporting and alerts
|
||||
|
||||
### Step 5: Update State Management
|
||||
```typescript
|
||||
// Add auto-recording state to your store/context
|
||||
interface AppState {
|
||||
cameras: CameraStatusResponse[];
|
||||
autoRecordingStatus: AutoRecordingStatusResponse;
|
||||
// ... existing state
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 Key User Experience Considerations
|
||||
|
||||
### Visual Indicators
|
||||
1. **Recording Status Hierarchy:**
|
||||
- Manual Recording (highest priority - red/prominent)
|
||||
- Auto-Recording Active (green/secondary)
|
||||
- Auto-Recording Enabled but Inactive (blue/subtle)
|
||||
- Auto-Recording Disabled (gray/muted)
|
||||
|
||||
2. **Machine State Correlation:**
|
||||
- Show machine ON/OFF status next to camera
|
||||
- Indicate when auto-recording should be active
|
||||
- Alert if machine is ON but auto-recording failed
|
||||
|
||||
3. **Error Handling:**
|
||||
- Clear error messages for auto-recording failures
|
||||
- Retry count display
|
||||
- Last attempt timestamp
|
||||
- Quick retry/reset options
|
||||
|
||||
### User Controls
|
||||
1. **Quick Actions:**
|
||||
- Toggle auto-recording per camera
|
||||
- Force retry failed auto-recording
|
||||
- Override auto-recording (manual control)
|
||||
|
||||
2. **Configuration:**
|
||||
- Adjust retry settings
|
||||
- Change machine-camera mappings
|
||||
- Set recording parameters for auto-recording
|
||||
|
||||
## 🚨 Important Notes
|
||||
|
||||
### Behavior Rules
|
||||
1. **Manual Override:** Manual recording always takes precedence over auto-recording
|
||||
2. **Non-Blocking:** Auto-recording status checks don't interfere with camera operation
|
||||
3. **Machine Correlation:** Auto-recording only activates when the associated machine turns ON
|
||||
4. **Failure Handling:** Failed auto-recording attempts are retried automatically with exponential backoff
|
||||
|
||||
### API Polling Recommendations
|
||||
- Poll camera status every 2-3 seconds for real-time updates
|
||||
- Poll auto-recording status every 5-10 seconds
|
||||
- Use WebSocket connections if available for real-time machine state updates
|
||||
|
||||
## 📱 Mobile Considerations
|
||||
- Auto-recording controls should be easily accessible on mobile
|
||||
- Status indicators should be clear and readable on small screens
|
||||
- Consider collapsible sections for detailed auto-recording information
|
||||
|
||||
## 🔍 Testing Checklist
|
||||
- [ ] Auto-recording toggle works for each camera
|
||||
- [ ] Status updates reflect machine state changes
|
||||
- [ ] Error states are clearly displayed
|
||||
- [ ] Manual recording overrides auto-recording
|
||||
- [ ] Retry mechanism is visible to users
|
||||
- [ ] Mobile interface is functional
|
||||
|
||||
This guide provides everything needed to update the React app to fully support the new auto-recording feature!
|
||||
158
camera-management-api/docs/guides/CAMERA_RECOVERY_GUIDE.md
Normal file
158
camera-management-api/docs/guides/CAMERA_RECOVERY_GUIDE.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Camera Recovery and Diagnostics Guide
|
||||
|
||||
This guide explains the new camera recovery functionality implemented in the USDA Vision Camera System API.
|
||||
|
||||
## Overview
|
||||
|
||||
The system now includes comprehensive camera recovery capabilities to handle connection issues, initialization failures, and other camera-related problems. These features use the underlying mvsdk (python demo) library functions to perform various recovery operations.
|
||||
|
||||
## Available Recovery Operations
|
||||
|
||||
### 1. Connection Test (`/cameras/{camera_name}/test-connection`)
|
||||
- **Purpose**: Test if the camera connection is working
|
||||
- **SDK Function**: `CameraConnectTest()`
|
||||
- **Use Case**: Diagnose connection issues
|
||||
- **HTTP Method**: POST
|
||||
- **Response**: `CameraTestResponse`
|
||||
|
||||
### 2. Reconnect (`/cameras/{camera_name}/reconnect`)
|
||||
- **Purpose**: Soft reconnection to the camera
|
||||
- **SDK Function**: `CameraReConnect()`
|
||||
- **Use Case**: Most common fix for connection issues
|
||||
- **HTTP Method**: POST
|
||||
- **Response**: `CameraRecoveryResponse`
|
||||
|
||||
### 3. Restart Grab (`/cameras/{camera_name}/restart-grab`)
|
||||
- **Purpose**: Restart the camera grab process
|
||||
- **SDK Function**: `CameraRestartGrab()`
|
||||
- **Use Case**: Fix issues with image capture
|
||||
- **HTTP Method**: POST
|
||||
- **Response**: `CameraRecoveryResponse`
|
||||
|
||||
### 4. Reset Timestamp (`/cameras/{camera_name}/reset-timestamp`)
|
||||
- **Purpose**: Reset camera timestamp
|
||||
- **SDK Function**: `CameraRstTimeStamp()`
|
||||
- **Use Case**: Fix timing-related issues
|
||||
- **HTTP Method**: POST
|
||||
- **Response**: `CameraRecoveryResponse`
|
||||
|
||||
### 5. Full Reset (`/cameras/{camera_name}/full-reset`)
|
||||
- **Purpose**: Complete camera reset (uninitialize and reinitialize)
|
||||
- **SDK Functions**: `CameraUnInit()` + `CameraInit()`
|
||||
- **Use Case**: Hard reset for persistent issues
|
||||
- **HTTP Method**: POST
|
||||
- **Response**: `CameraRecoveryResponse`
|
||||
|
||||
### 6. Reinitialize (`/cameras/{camera_name}/reinitialize`)
|
||||
- **Purpose**: Reinitialize cameras that failed initial setup
|
||||
- **SDK Functions**: Complete recorder recreation
|
||||
- **Use Case**: Cameras that never initialized properly
|
||||
- **HTTP Method**: POST
|
||||
- **Response**: `CameraRecoveryResponse`
|
||||
|
||||
## Recommended Troubleshooting Workflow
|
||||
|
||||
When a camera has issues, follow this order:
|
||||
|
||||
1. **Test Connection** - Diagnose the problem
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/test-connection
|
||||
```
|
||||
|
||||
2. **Try Reconnect** - Most common fix
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/reconnect
|
||||
```
|
||||
|
||||
3. **Restart Grab** - If reconnect doesn't work
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/restart-grab
|
||||
```
|
||||
|
||||
4. **Full Reset** - For persistent issues
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/full-reset
|
||||
```
|
||||
|
||||
5. **Reinitialize** - For cameras that never worked
|
||||
```http
|
||||
POST http://localhost:8000/cameras/camera1/reinitialize
|
||||
```
|
||||
|
||||
## Response Format
|
||||
|
||||
All recovery operations return structured responses:
|
||||
|
||||
### CameraTestResponse
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Camera camera1 connection test passed",
|
||||
"camera_name": "camera1",
|
||||
"timestamp": "2024-01-01T12:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
### CameraRecoveryResponse
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Camera camera1 reconnected successfully",
|
||||
"camera_name": "camera1",
|
||||
"operation": "reconnect",
|
||||
"timestamp": "2024-01-01T12:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### CameraRecorder Methods
|
||||
- `test_connection()`: Tests camera connection
|
||||
- `reconnect()`: Performs soft reconnection
|
||||
- `restart_grab()`: Restarts grab process
|
||||
- `reset_timestamp()`: Resets timestamp
|
||||
- `full_reset()`: Complete reset with cleanup and reinitialization
|
||||
|
||||
### CameraManager Methods
|
||||
- `test_camera_connection(camera_name)`: Test specific camera
|
||||
- `reconnect_camera(camera_name)`: Reconnect specific camera
|
||||
- `restart_camera_grab(camera_name)`: Restart grab for specific camera
|
||||
- `reset_camera_timestamp(camera_name)`: Reset timestamp for specific camera
|
||||
- `full_reset_camera(camera_name)`: Full reset for specific camera
|
||||
- `reinitialize_failed_camera(camera_name)`: Reinitialize failed camera
|
||||
|
||||
### State Management
|
||||
All recovery operations automatically update the camera status in the state manager:
|
||||
- Success: Status set to "connected"
|
||||
- Failure: Status set to appropriate error state with error message
|
||||
|
||||
## Error Handling
|
||||
|
||||
The system includes comprehensive error handling:
|
||||
- SDK exceptions are caught and logged
|
||||
- State manager is updated with error information
|
||||
- Proper HTTP status codes are returned
|
||||
- Detailed error messages are provided
|
||||
|
||||
## Testing
|
||||
|
||||
Use the provided test files:
|
||||
- `api-tests.http`: Manual API testing with VS Code REST Client
|
||||
- `test_camera_recovery_api.py`: Automated testing script
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Recording is automatically stopped before recovery operations
|
||||
- Camera resources are properly cleaned up
|
||||
- Thread-safe operations with proper locking
|
||||
- Graceful error handling prevents system crashes
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
1. **Camera Lost Connection**: Use reconnect
|
||||
2. **Camera Won't Capture**: Use restart-grab
|
||||
3. **Camera Initialization Failed**: Use reinitialize
|
||||
4. **Persistent Issues**: Use full-reset
|
||||
5. **Timing Problems**: Use reset-timestamp
|
||||
|
||||
This recovery system provides robust tools to handle most camera-related issues without requiring system restart or manual intervention.
|
||||
187
camera-management-api/docs/guides/MQTT_LOGGING_GUIDE.md
Normal file
187
camera-management-api/docs/guides/MQTT_LOGGING_GUIDE.md
Normal file
@@ -0,0 +1,187 @@
|
||||
# MQTT Console Logging & API Guide
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
Your USDA Vision Camera System now has **enhanced MQTT console logging** and **comprehensive API endpoints** for monitoring machine status via MQTT.
|
||||
|
||||
## ✨ What's New
|
||||
|
||||
### 1. **Enhanced Console Logging**
|
||||
- **Colorful emoji-based console output** for all MQTT events
|
||||
- **Real-time visibility** of MQTT connections, subscriptions, and messages
|
||||
- **Clear status indicators** for debugging and monitoring
|
||||
|
||||
### 2. **New MQTT Status API Endpoint**
|
||||
- **GET /mqtt/status** - Detailed MQTT client statistics
|
||||
- **Message counts, error tracking, uptime monitoring**
|
||||
- **Real-time connection status and broker information**
|
||||
|
||||
### 3. **Existing Machine Status APIs** (already available)
|
||||
- **GET /machines** - All machine states from MQTT
|
||||
- **GET /system/status** - Overall system status including MQTT
|
||||
|
||||
## 🖥️ Console Logging Examples
|
||||
|
||||
When you run the system, you'll see:
|
||||
|
||||
```bash
|
||||
🔗 MQTT CONNECTED: 192.168.1.110:1883
|
||||
📋 MQTT SUBSCRIBED: vibratory_conveyor → vision/vibratory_conveyor/state
|
||||
📋 MQTT SUBSCRIBED: blower_separator → vision/blower_separator/state
|
||||
📡 MQTT MESSAGE: vibratory_conveyor → on
|
||||
📡 MQTT MESSAGE: blower_separator → off
|
||||
⚠️ MQTT DISCONNECTED: Unexpected disconnection (code: 1)
|
||||
🔗 MQTT CONNECTED: 192.168.1.110:1883
|
||||
```
|
||||
|
||||
## 🌐 API Endpoints
|
||||
|
||||
### MQTT Status
|
||||
```http
|
||||
GET http://localhost:8000/mqtt/status
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"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
|
||||
}
|
||||
```
|
||||
|
||||
### Machine Status
|
||||
```http
|
||||
GET http://localhost:8000/machines
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"vibratory_conveyor": {
|
||||
"name": "vibratory_conveyor",
|
||||
"state": "on",
|
||||
"last_updated": "2025-07-28T12:00:00",
|
||||
"last_message": "on",
|
||||
"mqtt_topic": "vision/vibratory_conveyor/state"
|
||||
},
|
||||
"blower_separator": {
|
||||
"name": "blower_separator",
|
||||
"state": "off",
|
||||
"last_updated": "2025-07-28T12:00:00",
|
||||
"last_message": "off",
|
||||
"mqtt_topic": "vision/blower_separator/state"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### System Status
|
||||
```http
|
||||
GET http://localhost:8000/system/status
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"system_started": true,
|
||||
"mqtt_connected": true,
|
||||
"last_mqtt_message": "2025-07-28T12:00:00",
|
||||
"machines": { ... },
|
||||
"cameras": { ... },
|
||||
"active_recordings": 0,
|
||||
"total_recordings": 5,
|
||||
"uptime_seconds": 3600.5
|
||||
}
|
||||
```
|
||||
|
||||
## 🚀 How to Use
|
||||
|
||||
### 1. **Start the Full System**
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
You'll see enhanced console logging for all MQTT events.
|
||||
|
||||
### 2. **Test MQTT Demo (MQTT only)**
|
||||
```bash
|
||||
python demo_mqtt_console.py
|
||||
```
|
||||
Shows just the MQTT client with enhanced logging.
|
||||
|
||||
### 3. **Test API Endpoints**
|
||||
```bash
|
||||
python test_mqtt_logging.py
|
||||
```
|
||||
Tests all the API endpoints and shows expected responses.
|
||||
|
||||
### 4. **Query APIs Directly**
|
||||
```bash
|
||||
# Check MQTT status
|
||||
curl http://localhost:8000/mqtt/status
|
||||
|
||||
# Check machine states
|
||||
curl http://localhost:8000/machines
|
||||
|
||||
# Check overall system status
|
||||
curl http://localhost:8000/system/status
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
The MQTT settings are in `config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"mqtt": {
|
||||
"broker_host": "192.168.1.110",
|
||||
"broker_port": 1883,
|
||||
"username": null,
|
||||
"password": null,
|
||||
"topics": {
|
||||
"vibratory_conveyor": "vision/vibratory_conveyor/state",
|
||||
"blower_separator": "vision/blower_separator/state"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎨 Console Output Features
|
||||
|
||||
- **🔗 Connection Events**: Green for successful connections
|
||||
- **📋 Subscriptions**: Blue for topic subscriptions
|
||||
- **📡 Messages**: Real-time message display with machine name and payload
|
||||
- **⚠️ Warnings**: Yellow for unexpected disconnections
|
||||
- **❌ Errors**: Red for connection failures and errors
|
||||
- **❓ Unknown Topics**: Purple for unrecognized MQTT topics
|
||||
|
||||
## 📊 Monitoring & Debugging
|
||||
|
||||
### Real-time Monitoring
|
||||
- **Console**: Watch live MQTT events as they happen
|
||||
- **API**: Query `/mqtt/status` for statistics and health
|
||||
- **Logs**: Check `usda_vision_system.log` for detailed logs
|
||||
|
||||
### Troubleshooting
|
||||
1. **No MQTT messages?** Check broker connectivity and topic configuration
|
||||
2. **Connection issues?** Verify broker host/port in config.json
|
||||
3. **API not responding?** Ensure the system is running with `python main.py`
|
||||
|
||||
## 🎯 Use Cases
|
||||
|
||||
1. **Development**: See MQTT messages in real-time while developing
|
||||
2. **Debugging**: Identify connection issues and message patterns
|
||||
3. **Monitoring**: Use APIs to build dashboards or monitoring tools
|
||||
4. **Integration**: Query machine states from external applications
|
||||
5. **Maintenance**: Track MQTT statistics and error rates
|
||||
|
||||
---
|
||||
|
||||
**🎉 Your MQTT monitoring is now fully enhanced with both console logging and comprehensive APIs!**
|
||||
240
camera-management-api/docs/guides/STREAMING_GUIDE.md
Normal file
240
camera-management-api/docs/guides/STREAMING_GUIDE.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# 🎥 USDA Vision Camera Live Streaming Guide
|
||||
|
||||
This guide explains how to use the new live preview streaming functionality that allows you to view camera feeds in real-time without blocking recording operations.
|
||||
|
||||
## 🌟 Key Features
|
||||
|
||||
- **Non-blocking streaming**: Live preview doesn't interfere with recording
|
||||
- **Separate camera connections**: Streaming uses independent camera instances
|
||||
- **MJPEG streaming**: Standard web-compatible video streaming
|
||||
- **Multiple concurrent viewers**: Multiple browsers can view the same stream
|
||||
- **REST API control**: Start/stop streaming via API endpoints
|
||||
- **Web interface**: Ready-to-use HTML interface for live preview
|
||||
|
||||
## 🏗️ Architecture
|
||||
|
||||
The streaming system creates separate camera connections for preview that are independent from recording:
|
||||
|
||||
```
|
||||
Camera Hardware
|
||||
├── Recording Connection (CameraRecorder)
|
||||
│ ├── Used for video file recording
|
||||
│ ├── Triggered by MQTT machine states
|
||||
│ └── High quality, full FPS
|
||||
└── Streaming Connection (CameraStreamer)
|
||||
├── Used for live preview
|
||||
├── Controlled via API endpoints
|
||||
└── Optimized for web viewing (lower FPS, JPEG compression)
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 1. Start the System
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
### 2. Open the Web Interface
|
||||
Open `camera_preview.html` in your browser and click "Start Stream" for any camera.
|
||||
|
||||
### 3. API Usage
|
||||
```bash
|
||||
# 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
|
||||
```
|
||||
|
||||
## 📡 API Endpoints
|
||||
|
||||
### Start Streaming
|
||||
```http
|
||||
POST /cameras/{camera_name}/start-stream
|
||||
```
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Started streaming for camera camera1"
|
||||
}
|
||||
```
|
||||
|
||||
### Stop Streaming
|
||||
```http
|
||||
POST /cameras/{camera_name}/stop-stream
|
||||
```
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Stopped streaming for camera camera1"
|
||||
}
|
||||
```
|
||||
|
||||
### Live Stream (MJPEG)
|
||||
```http
|
||||
GET /cameras/{camera_name}/stream
|
||||
```
|
||||
**Response:** Multipart MJPEG stream
|
||||
**Content-Type:** `multipart/x-mixed-replace; boundary=frame`
|
||||
|
||||
## 🌐 Web Interface Usage
|
||||
|
||||
The included `camera_preview.html` provides a complete web interface:
|
||||
|
||||
1. **Camera Grid**: Shows all configured cameras
|
||||
2. **Stream Controls**: Start/Stop/Refresh buttons for each camera
|
||||
3. **Live Preview**: Real-time video feed display
|
||||
4. **Status Information**: System and camera status
|
||||
5. **Responsive Design**: Works on desktop and mobile
|
||||
|
||||
### Features:
|
||||
- ✅ Real-time camera status
|
||||
- ✅ One-click stream start/stop
|
||||
- ✅ Automatic stream refresh
|
||||
- ✅ System health monitoring
|
||||
- ✅ Error handling and status messages
|
||||
|
||||
## 🔧 Technical Details
|
||||
|
||||
### Camera Streamer Configuration
|
||||
- **Preview FPS**: 10 FPS (configurable)
|
||||
- **JPEG Quality**: 70% (configurable)
|
||||
- **Frame Buffer**: 5 frames (prevents memory buildup)
|
||||
- **Timeout**: 200ms per frame capture
|
||||
|
||||
### Memory Management
|
||||
- Automatic frame buffer cleanup
|
||||
- Queue-based frame management
|
||||
- Proper camera resource cleanup on stop
|
||||
|
||||
### Thread Safety
|
||||
- Thread-safe streaming operations
|
||||
- Independent from recording threads
|
||||
- Proper synchronization with locks
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Run the Test Script
|
||||
```bash
|
||||
python test_streaming.py
|
||||
```
|
||||
|
||||
This will test:
|
||||
- ✅ API endpoint functionality
|
||||
- ✅ Stream start/stop operations
|
||||
- ✅ Concurrent recording and streaming
|
||||
- ✅ Error handling
|
||||
|
||||
### Manual Testing
|
||||
1. Start the system: `python main.py`
|
||||
2. Open `camera_preview.html` in browser
|
||||
3. Start streaming for a camera
|
||||
4. Trigger recording via MQTT or manual API
|
||||
5. Verify both work simultaneously
|
||||
|
||||
## 🔄 Concurrent Operations
|
||||
|
||||
The system supports these concurrent operations:
|
||||
|
||||
| Operation | Recording | Streaming | Notes |
|
||||
|-----------|-----------|-----------|-------|
|
||||
| Recording Only | ✅ | ❌ | Normal operation |
|
||||
| Streaming Only | ❌ | ✅ | Preview without recording |
|
||||
| Both Concurrent | ✅ | ✅ | **Independent connections** |
|
||||
|
||||
### Example: Concurrent Usage
|
||||
```bash
|
||||
# Start streaming
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-stream
|
||||
|
||||
# Start recording (while streaming continues)
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"filename": "test_recording.avi"}'
|
||||
|
||||
# Both operations run independently!
|
||||
```
|
||||
|
||||
## 🛠️ Configuration
|
||||
|
||||
### Stream Settings (in CameraStreamer)
|
||||
```python
|
||||
self.preview_fps = 10.0 # Lower FPS for preview
|
||||
self.preview_quality = 70 # JPEG quality (1-100)
|
||||
self._frame_queue.maxsize = 5 # Frame buffer size
|
||||
```
|
||||
|
||||
### Camera Settings
|
||||
The streamer uses the same camera configuration as recording:
|
||||
- Exposure time from `camera_config.exposure_ms`
|
||||
- Gain from `camera_config.gain`
|
||||
- Optimized trigger mode for continuous streaming
|
||||
|
||||
## 🚨 Important Notes
|
||||
|
||||
### Camera Access Patterns
|
||||
- **Recording**: Blocks camera during active recording
|
||||
- **Streaming**: Uses separate connection, doesn't block
|
||||
- **Health Checks**: Brief, non-blocking camera tests
|
||||
- **Multiple Streams**: Multiple browsers can view same stream
|
||||
|
||||
### Performance Considerations
|
||||
- Streaming uses additional CPU/memory resources
|
||||
- Lower preview FPS reduces system load
|
||||
- JPEG compression reduces bandwidth usage
|
||||
- Frame queue prevents memory buildup
|
||||
|
||||
### Error Handling
|
||||
- Automatic camera resource cleanup
|
||||
- Graceful handling of camera disconnections
|
||||
- Stream auto-restart capabilities
|
||||
- Detailed error logging
|
||||
|
||||
## 🔍 Troubleshooting
|
||||
|
||||
### Stream Not Starting
|
||||
1. Check camera availability: `GET /cameras`
|
||||
2. Verify camera not in error state
|
||||
3. Check system logs for camera initialization errors
|
||||
4. Try camera reconnection: `POST /cameras/{name}/reconnect`
|
||||
|
||||
### Poor Stream Quality
|
||||
1. Adjust `preview_quality` setting (higher = better quality)
|
||||
2. Increase `preview_fps` for smoother video
|
||||
3. Check network bandwidth
|
||||
4. Verify camera exposure/gain settings
|
||||
|
||||
### Browser Issues
|
||||
1. Try different browser (Chrome/Firefox recommended)
|
||||
2. Check browser console for JavaScript errors
|
||||
3. Verify CORS settings in API server
|
||||
4. Clear browser cache and refresh
|
||||
|
||||
## 📈 Future Enhancements
|
||||
|
||||
Potential improvements for the streaming system:
|
||||
|
||||
- 🔄 WebRTC support for lower latency
|
||||
- 📱 Mobile app integration
|
||||
- 🎛️ Real-time camera setting adjustments
|
||||
- 📊 Stream analytics and monitoring
|
||||
- 🔐 Authentication and access control
|
||||
- 🌐 Multi-camera synchronized viewing
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For issues with streaming functionality:
|
||||
|
||||
1. Check the system logs: `usda_vision_system.log`
|
||||
2. Run the test script: `python test_streaming.py`
|
||||
3. Verify API health: `http://localhost:8000/health`
|
||||
4. Check camera status: `http://localhost:8000/cameras`
|
||||
|
||||
---
|
||||
|
||||
**✅ Live streaming is now ready for production use!**
|
||||
146
camera-management-api/docs/legacy/01README.md
Normal file
146
camera-management-api/docs/legacy/01README.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# GigE Camera Image Capture
|
||||
|
||||
This project provides simple Python scripts to connect to a GigE camera and capture images using the provided SDK.
|
||||
|
||||
## Files Overview
|
||||
|
||||
### Demo Files (provided with camera)
|
||||
- `python demo/mvsdk.py` - Main SDK wrapper library
|
||||
- `python demo/grab.py` - Basic image capture example
|
||||
- `python demo/cv_grab.py` - OpenCV-based continuous capture
|
||||
- `python demo/cv_grab_callback.py` - Callback-based capture
|
||||
- `python demo/readme.txt` - Original demo documentation
|
||||
|
||||
### Custom Scripts
|
||||
- `camera_capture.py` - Standalone script to capture 10 images with 200ms intervals
|
||||
- `test.ipynb` - Jupyter notebook with the same functionality
|
||||
- `images/` - Directory where captured images are saved
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic camera detection** - Finds and connects to available GigE cameras
|
||||
- **Configurable capture** - Currently set to capture 10 images with 200ms intervals
|
||||
- **Both mono and color support** - Automatically detects camera type
|
||||
- **Timestamped filenames** - Images saved with date/time stamps
|
||||
- **Error handling** - Robust error handling for camera operations
|
||||
- **Cross-platform** - Works on Windows and Linux (with appropriate image flipping)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.x
|
||||
- OpenCV (`cv2`)
|
||||
- NumPy
|
||||
- Matplotlib (for Jupyter notebook display)
|
||||
- GigE camera SDK (MVSDK) - included in `python demo/` directory
|
||||
|
||||
## Usage
|
||||
|
||||
### Option 1: Standalone Script
|
||||
|
||||
Run the standalone Python script:
|
||||
|
||||
```bash
|
||||
python camera_capture.py
|
||||
```
|
||||
|
||||
This will:
|
||||
1. Initialize the camera SDK
|
||||
2. Detect available cameras
|
||||
3. Connect to the first camera found
|
||||
4. Configure camera settings (manual exposure, continuous mode)
|
||||
5. Capture 10 images with 200ms intervals
|
||||
6. Save images to the `images/` directory
|
||||
7. Clean up and close the camera
|
||||
|
||||
### Option 2: Jupyter Notebook
|
||||
|
||||
Open and run the `test.ipynb` notebook:
|
||||
|
||||
```bash
|
||||
jupyter notebook test.ipynb
|
||||
```
|
||||
|
||||
The notebook provides the same functionality but with:
|
||||
- Step-by-step execution
|
||||
- Detailed explanations
|
||||
- Visual display of the last captured image
|
||||
- Better error reporting
|
||||
|
||||
## Camera Configuration
|
||||
|
||||
The scripts are configured with the following default settings:
|
||||
|
||||
- **Trigger Mode**: Continuous capture (mode 0)
|
||||
- **Exposure**: Manual, 30ms
|
||||
- **Output Format**:
|
||||
- Monochrome cameras: MONO8
|
||||
- Color cameras: BGR8
|
||||
- **Image Processing**: Automatic ISP processing from RAW to RGB/MONO
|
||||
|
||||
## Output
|
||||
|
||||
Images are saved in the `images/` directory with the following naming convention:
|
||||
```
|
||||
image_XX_YYYYMMDD_HHMMSS_mmm.jpg
|
||||
```
|
||||
|
||||
Where:
|
||||
- `XX` = Image number (01-10)
|
||||
- `YYYYMMDD_HHMMSS_mmm` = Timestamp with milliseconds
|
||||
|
||||
Example: `image_01_20250722_140530_123.jpg`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **"No camera was found!"**
|
||||
- Check camera connection (Ethernet cable)
|
||||
- Verify camera power
|
||||
- Check network settings (camera and PC should be on same subnet)
|
||||
- Ensure camera drivers are installed
|
||||
|
||||
2. **"CameraInit Failed"**
|
||||
- Camera might be in use by another application
|
||||
- Check camera permissions
|
||||
- Try restarting the camera or PC
|
||||
|
||||
3. **"Failed to capture image"**
|
||||
- Check camera settings
|
||||
- Verify sufficient lighting
|
||||
- Check exposure settings
|
||||
|
||||
4. **Images appear upside down**
|
||||
- This is handled automatically on Windows
|
||||
- Linux users may need to adjust the flip settings
|
||||
|
||||
### Network Configuration
|
||||
|
||||
For GigE cameras, ensure:
|
||||
- Camera and PC are on the same network segment
|
||||
- PC network adapter supports Jumbo frames (recommended)
|
||||
- Firewall allows camera communication
|
||||
- Sufficient network bandwidth
|
||||
|
||||
## Customization
|
||||
|
||||
You can modify the scripts to:
|
||||
|
||||
- **Change capture count**: Modify the range in the capture loop
|
||||
- **Adjust timing**: Change the `time.sleep(0.2)` value
|
||||
- **Modify exposure**: Change the exposure time parameter
|
||||
- **Change output format**: Modify file format and quality settings
|
||||
- **Add image processing**: Insert processing steps before saving
|
||||
|
||||
## SDK Reference
|
||||
|
||||
The camera SDK (`mvsdk.py`) provides extensive functionality:
|
||||
|
||||
- Camera enumeration and initialization
|
||||
- Image capture and processing
|
||||
- Parameter configuration (exposure, gain, etc.)
|
||||
- Trigger modes and timing
|
||||
- Image format conversion
|
||||
- Error handling
|
||||
|
||||
Refer to the original SDK documentation for advanced features.
|
||||
184
camera-management-api/docs/legacy/IMPLEMENTATION_SUMMARY.md
Normal file
184
camera-management-api/docs/legacy/IMPLEMENTATION_SUMMARY.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# USDA Vision Camera System - Implementation Summary
|
||||
|
||||
## 🎉 Project Completed Successfully!
|
||||
|
||||
The USDA Vision Camera System has been fully implemented and tested. All components are working correctly and the system is ready for deployment.
|
||||
|
||||
## ✅ What Was Built
|
||||
|
||||
### Core Architecture
|
||||
- **Modular Design**: Clean separation of concerns across multiple modules
|
||||
- **Multi-threading**: Concurrent MQTT listening, camera monitoring, and recording
|
||||
- **Event-driven**: Thread-safe communication between components
|
||||
- **Configuration-driven**: JSON-based configuration system
|
||||
|
||||
### Key Components
|
||||
|
||||
1. **MQTT Integration** (`usda_vision_system/mqtt/`)
|
||||
- Listens to two machine topics: `vision/vibratory_conveyor/state` and `vision/blower_separator/state`
|
||||
- Thread-safe message handling with automatic reconnection
|
||||
- State normalization (on/off/error)
|
||||
|
||||
2. **Camera Management** (`usda_vision_system/camera/`)
|
||||
- Automatic GigE camera discovery using python demo library
|
||||
- Periodic status monitoring (every 2 seconds)
|
||||
- Camera initialization and configuration management
|
||||
- **Discovered Cameras**:
|
||||
- Blower-Yield-Cam (192.168.1.165)
|
||||
- Cracker-Cam (192.168.1.167)
|
||||
|
||||
3. **Video Recording** (`usda_vision_system/camera/recorder.py`)
|
||||
- Automatic recording start/stop based on machine states
|
||||
- Timestamp-based file naming: `camera1_recording_20250726_143022.avi`
|
||||
- Configurable FPS, exposure, and gain settings
|
||||
- Thread-safe recording with proper cleanup
|
||||
|
||||
4. **Storage Management** (`usda_vision_system/storage/`)
|
||||
- Organized file storage under `./storage/camera1/` and `./storage/camera2/`
|
||||
- File indexing and metadata tracking
|
||||
- Automatic cleanup of old files
|
||||
- Storage statistics and integrity checking
|
||||
|
||||
5. **REST API Server** (`usda_vision_system/api/`)
|
||||
- FastAPI server on port 8000
|
||||
- Real-time WebSocket updates
|
||||
- Manual recording control endpoints
|
||||
- System status and monitoring endpoints
|
||||
|
||||
6. **Comprehensive Logging** (`usda_vision_system/core/logging_config.py`)
|
||||
- Colored console output
|
||||
- Rotating log files
|
||||
- Component-specific log levels
|
||||
- Performance monitoring and error tracking
|
||||
|
||||
## 🚀 How to Use
|
||||
|
||||
### Quick Start
|
||||
```bash
|
||||
# Run system tests
|
||||
python test_system.py
|
||||
|
||||
# Start the system
|
||||
python main.py
|
||||
|
||||
# Or use the startup script
|
||||
./start_system.sh
|
||||
```
|
||||
|
||||
### Configuration
|
||||
Edit `config.json` to customize:
|
||||
- MQTT broker settings
|
||||
- Camera configurations
|
||||
- Storage paths
|
||||
- System parameters
|
||||
|
||||
### API Access
|
||||
- System status: `http://localhost:8000/system/status`
|
||||
- Camera status: `http://localhost:8000/cameras`
|
||||
- Manual recording: `POST http://localhost:8000/cameras/camera1/start-recording`
|
||||
- Real-time updates: WebSocket at `ws://localhost:8000/ws`
|
||||
|
||||
## 📊 Test Results
|
||||
|
||||
All system tests passed successfully:
|
||||
- ✅ Module imports
|
||||
- ✅ Configuration loading
|
||||
- ✅ Camera discovery (found 2 cameras)
|
||||
- ✅ Storage setup
|
||||
- ✅ MQTT configuration
|
||||
- ✅ System initialization
|
||||
- ✅ API endpoints
|
||||
|
||||
## 🔧 System Behavior
|
||||
|
||||
### Automatic Recording Flow
|
||||
1. **Machine turns ON** → MQTT message received → Recording starts automatically
|
||||
2. **Machine turns OFF** → MQTT message received → Recording stops and saves file
|
||||
3. **Files saved** with timestamp: `camera1_recording_YYYYMMDD_HHMMSS.avi`
|
||||
|
||||
### Manual Control
|
||||
- Start/stop recording via API calls
|
||||
- Monitor system status in real-time
|
||||
- Check camera availability on demand
|
||||
|
||||
### Dashboard Integration
|
||||
The system is designed to integrate with your React + Vite + Tailwind + Supabase dashboard:
|
||||
- REST API for status queries
|
||||
- WebSocket for real-time updates
|
||||
- JSON responses for easy frontend consumption
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
usda_vision_system/
|
||||
├── core/ # Configuration, state management, events, logging
|
||||
├── mqtt/ # MQTT client and message handlers
|
||||
├── camera/ # Camera management, monitoring, recording
|
||||
├── storage/ # File organization and management
|
||||
├── api/ # FastAPI server and WebSocket support
|
||||
└── main.py # Application coordinator
|
||||
|
||||
Supporting Files:
|
||||
├── main.py # Entry point script
|
||||
├── config.json # System configuration
|
||||
├── test_system.py # Test suite
|
||||
├── start_system.sh # Startup script
|
||||
└── README_SYSTEM.md # Comprehensive documentation
|
||||
```
|
||||
|
||||
## 🎯 Key Features Delivered
|
||||
|
||||
- ✅ **Dual MQTT topic listening** for two machines
|
||||
- ✅ **Automatic camera recording** triggered by machine states
|
||||
- ✅ **GigE camera support** using python demo library
|
||||
- ✅ **Thread-safe multi-tasking** (MQTT + camera monitoring + recording)
|
||||
- ✅ **Timestamp-based file naming** in organized directories
|
||||
- ✅ **2-second camera status monitoring** with on-demand checks
|
||||
- ✅ **REST API and WebSocket** for dashboard integration
|
||||
- ✅ **Comprehensive logging** with error tracking
|
||||
- ✅ **Configuration management** via JSON
|
||||
- ✅ **Storage management** with cleanup capabilities
|
||||
- ✅ **Graceful startup/shutdown** with signal handling
|
||||
|
||||
## 🔮 Ready for Dashboard Integration
|
||||
|
||||
The system provides everything needed for your React dashboard:
|
||||
|
||||
```javascript
|
||||
// Example API usage
|
||||
const systemStatus = await fetch('http://localhost:8000/system/status');
|
||||
const cameras = await fetch('http://localhost:8000/cameras');
|
||||
|
||||
// WebSocket for real-time updates
|
||||
const ws = new WebSocket('ws://localhost:8000/ws');
|
||||
ws.onmessage = (event) => {
|
||||
const update = JSON.parse(event.data);
|
||||
// Handle real-time system updates
|
||||
};
|
||||
|
||||
// Manual recording control
|
||||
await fetch('http://localhost:8000/cameras/camera1/start-recording', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ camera_name: 'camera1' })
|
||||
});
|
||||
```
|
||||
|
||||
## 🎊 Next Steps
|
||||
|
||||
The system is production-ready! You can now:
|
||||
|
||||
1. **Deploy** the system on your target hardware
|
||||
2. **Integrate** with your existing React dashboard
|
||||
3. **Configure** MQTT topics and camera settings as needed
|
||||
4. **Monitor** system performance through logs and API endpoints
|
||||
5. **Extend** functionality as requirements evolve
|
||||
|
||||
The modular architecture makes it easy to add new features, cameras, or MQTT topics in the future.
|
||||
|
||||
---
|
||||
|
||||
**System Status**: ✅ **FULLY OPERATIONAL**
|
||||
**Test Results**: ✅ **ALL TESTS PASSING**
|
||||
**Cameras Detected**: ✅ **2 GIGE CAMERAS READY**
|
||||
**Ready for Production**: ✅ **YES**
|
||||
1
camera-management-api/docs/legacy/README.md
Normal file
1
camera-management-api/docs/legacy/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# USDA-Vision-Cameras
|
||||
249
camera-management-api/docs/legacy/README_SYSTEM.md
Normal file
249
camera-management-api/docs/legacy/README_SYSTEM.md
Normal file
@@ -0,0 +1,249 @@
|
||||
# USDA Vision Camera System
|
||||
|
||||
A comprehensive system for monitoring machines via MQTT and automatically recording video from GigE cameras when machines are active.
|
||||
|
||||
## Overview
|
||||
|
||||
This system integrates MQTT machine monitoring with automated video recording from GigE cameras. When a machine turns on (detected via MQTT), the system automatically starts recording from the associated camera. When the machine turns off, recording stops and the video is saved with a timestamp.
|
||||
|
||||
## Features
|
||||
|
||||
- **MQTT Integration**: Listens to multiple machine state topics
|
||||
- **Automatic Recording**: Starts/stops recording based on machine states
|
||||
- **GigE Camera Support**: Uses the python demo library (mvsdk) for camera control
|
||||
- **Multi-threading**: Concurrent MQTT listening, camera monitoring, and recording
|
||||
- **REST API**: FastAPI server for dashboard integration
|
||||
- **WebSocket Support**: Real-time status updates
|
||||
- **Storage Management**: Organized file storage with cleanup capabilities
|
||||
- **Comprehensive Logging**: Detailed logging with rotation and error tracking
|
||||
- **Configuration Management**: JSON-based configuration system
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ MQTT Broker │ │ GigE Camera │ │ Dashboard │
|
||||
│ │ │ │ │ (React) │
|
||||
└─────────┬───────┘ └─────────┬───────┘ └─────────┬───────┘
|
||||
│ │ │
|
||||
│ Machine States │ Video Streams │ API Calls
|
||||
│ │ │
|
||||
┌─────────▼──────────────────────▼──────────────────────▼───────┐
|
||||
│ USDA Vision Camera System │
|
||||
├───────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ MQTT Client │ │ Camera │ │ API Server │ │
|
||||
│ │ │ │ Manager │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ State │ │ Storage │ │ Event │ │
|
||||
│ │ Manager │ │ Manager │ │ System │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Prerequisites**:
|
||||
- Python 3.11+
|
||||
- GigE cameras with python demo library
|
||||
- MQTT broker (e.g., Mosquitto)
|
||||
- uv package manager (recommended)
|
||||
|
||||
2. **Install Dependencies**:
|
||||
```bash
|
||||
uv sync
|
||||
```
|
||||
|
||||
3. **Setup Storage Directory**:
|
||||
```bash
|
||||
sudo mkdir -p /storage
|
||||
sudo chown $USER:$USER /storage
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `config.json` to configure your system:
|
||||
|
||||
```json
|
||||
{
|
||||
"mqtt": {
|
||||
"broker_host": "192.168.1.110",
|
||||
"broker_port": 1883,
|
||||
"topics": {
|
||||
"vibratory_conveyor": "vision/vibratory_conveyor/state",
|
||||
"blower_separator": "vision/blower_separator/state"
|
||||
}
|
||||
},
|
||||
"cameras": [
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "vibratory_conveyor",
|
||||
"storage_path": "/storage/camera1",
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.5,
|
||||
"target_fps": 3.0,
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
1. **Start the System**:
|
||||
```bash
|
||||
python main.py
|
||||
```
|
||||
|
||||
2. **With Custom Config**:
|
||||
```bash
|
||||
python main.py --config my_config.json
|
||||
```
|
||||
|
||||
3. **Debug Mode**:
|
||||
```bash
|
||||
python main.py --log-level DEBUG
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
|
||||
The system provides a REST API on port 8000:
|
||||
|
||||
- `GET /system/status` - Overall system status
|
||||
- `GET /cameras` - All camera statuses
|
||||
- `GET /machines` - All machine states
|
||||
- `POST /cameras/{name}/start-recording` - Manual recording start
|
||||
- `POST /cameras/{name}/stop-recording` - Manual recording stop
|
||||
- `GET /storage/stats` - Storage statistics
|
||||
- `WebSocket /ws` - Real-time updates
|
||||
|
||||
### Dashboard Integration
|
||||
|
||||
The system is designed to integrate with your existing React + Vite + Tailwind + Supabase dashboard:
|
||||
|
||||
1. **API Integration**: Use the REST endpoints to display system status
|
||||
2. **WebSocket**: Connect to `/ws` for real-time updates
|
||||
3. **Supabase Storage**: Store recording metadata and system logs
|
||||
|
||||
## File Organization
|
||||
|
||||
```
|
||||
/storage/
|
||||
├── camera1/
|
||||
│ ├── camera1_recording_20250726_143022.avi
|
||||
│ └── camera1_recording_20250726_143155.avi
|
||||
├── camera2/
|
||||
│ ├── camera2_recording_20250726_143025.avi
|
||||
│ └── camera2_recording_20250726_143158.avi
|
||||
└── file_index.json
|
||||
```
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Log Files
|
||||
|
||||
- `usda_vision_system.log` - Main system log (rotated)
|
||||
- Console output with colored formatting
|
||||
- Component-specific log levels
|
||||
|
||||
### Performance Monitoring
|
||||
|
||||
The system includes built-in performance monitoring:
|
||||
- Startup times
|
||||
- Recording session metrics
|
||||
- MQTT message processing rates
|
||||
- Camera status check intervals
|
||||
|
||||
### Error Tracking
|
||||
|
||||
Comprehensive error tracking with:
|
||||
- Error counts per component
|
||||
- Detailed error context
|
||||
- Automatic recovery attempts
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Camera Not Found**:
|
||||
- Check camera connections
|
||||
- Verify python demo library installation
|
||||
- Run camera discovery: Check logs for enumeration results
|
||||
|
||||
2. **MQTT Connection Failed**:
|
||||
- Verify broker IP and port
|
||||
- Check network connectivity
|
||||
- Verify credentials if authentication is enabled
|
||||
|
||||
3. **Recording Fails**:
|
||||
- Check storage permissions
|
||||
- Verify available disk space
|
||||
- Check camera initialization logs
|
||||
|
||||
4. **API Server Won't Start**:
|
||||
- Check if port 8000 is available
|
||||
- Verify FastAPI dependencies
|
||||
- Check firewall settings
|
||||
|
||||
### Debug Commands
|
||||
|
||||
```bash
|
||||
# Check system status
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# Check camera status
|
||||
curl http://localhost:8000/cameras
|
||||
|
||||
# Manual recording start
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"camera_name": "camera1"}'
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
usda_vision_system/
|
||||
├── core/ # Core functionality
|
||||
├── mqtt/ # MQTT client and handlers
|
||||
├── camera/ # Camera management and recording
|
||||
├── storage/ # File management
|
||||
├── api/ # FastAPI server
|
||||
└── main.py # Application coordinator
|
||||
```
|
||||
|
||||
### Adding New Features
|
||||
|
||||
1. **New Camera Type**: Extend `camera/recorder.py`
|
||||
2. **New MQTT Topics**: Update `config.json` and `mqtt/handlers.py`
|
||||
3. **New API Endpoints**: Add to `api/server.py`
|
||||
4. **New Events**: Define in `core/events.py`
|
||||
|
||||
### Testing
|
||||
|
||||
```bash
|
||||
# Run basic system test
|
||||
python -c "from usda_vision_system import USDAVisionSystem; s = USDAVisionSystem(); print('OK')"
|
||||
|
||||
# Test MQTT connection
|
||||
python -c "from usda_vision_system.mqtt.client import MQTTClient; # ... test code"
|
||||
|
||||
# Test camera discovery
|
||||
python -c "import sys; sys.path.append('python demo'); import mvsdk; print(len(mvsdk.CameraEnumerateDevice()))"
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is developed for USDA research purposes.
|
||||
|
||||
## Support
|
||||
|
||||
For issues and questions:
|
||||
1. Check the logs in `usda_vision_system.log`
|
||||
2. Review the troubleshooting section
|
||||
3. Check API status at `http://localhost:8000/health`
|
||||
190
camera-management-api/docs/legacy/TIMEZONE_SETUP_SUMMARY.md
Normal file
190
camera-management-api/docs/legacy/TIMEZONE_SETUP_SUMMARY.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Time Synchronization Setup - Atlanta, Georgia
|
||||
|
||||
## ✅ Time Synchronization Complete!
|
||||
|
||||
The USDA Vision Camera System has been configured for proper time synchronization with Atlanta, Georgia (Eastern Time Zone).
|
||||
|
||||
## 🕐 What Was Implemented
|
||||
|
||||
### System-Level Time Configuration
|
||||
- **Timezone**: Set to `America/New_York` (Eastern Time)
|
||||
- **Current Status**: Eastern Daylight Time (EDT, UTC-4)
|
||||
- **NTP Sync**: Configured with multiple reliable time servers
|
||||
- **Hardware Clock**: Synchronized with system time
|
||||
|
||||
### Application-Level Timezone Support
|
||||
- **Timezone-Aware Timestamps**: All recordings use Atlanta time
|
||||
- **Automatic DST Handling**: Switches between EST/EDT automatically
|
||||
- **Time Sync Monitoring**: Built-in time synchronization checking
|
||||
- **Consistent Formatting**: Standardized timestamp formats throughout
|
||||
|
||||
## 🔧 Key Features
|
||||
|
||||
### 1. Automatic Time Synchronization
|
||||
```bash
|
||||
# NTP servers configured:
|
||||
- time.nist.gov (NIST atomic clock)
|
||||
- pool.ntp.org (NTP pool)
|
||||
- time.google.com (Google time)
|
||||
- time.cloudflare.com (Cloudflare time)
|
||||
```
|
||||
|
||||
### 2. Timezone-Aware Recording Filenames
|
||||
```
|
||||
Example: camera1_recording_20250725_213241.avi
|
||||
Format: {camera}_{type}_{YYYYMMDD_HHMMSS}.avi
|
||||
Time: Atlanta local time (EDT/EST)
|
||||
```
|
||||
|
||||
### 3. Time Verification Tools
|
||||
- **Startup Check**: Automatic time sync verification on system start
|
||||
- **Manual Check**: `python check_time.py` for on-demand verification
|
||||
- **API Integration**: Time sync status available via REST API
|
||||
|
||||
### 4. Comprehensive Logging
|
||||
```
|
||||
=== TIME SYNCHRONIZATION STATUS ===
|
||||
System time: 2025-07-25 21:32:41 EDT
|
||||
Timezone: EDT (-0400)
|
||||
Daylight Saving: Yes
|
||||
Sync status: synchronized
|
||||
Time difference: 0.10 seconds
|
||||
=====================================
|
||||
```
|
||||
|
||||
## 🚀 Usage
|
||||
|
||||
### Automatic Operation
|
||||
The system automatically:
|
||||
- Uses Atlanta time for all timestamps
|
||||
- Handles daylight saving time transitions
|
||||
- Monitors time synchronization status
|
||||
- Logs time-related events
|
||||
|
||||
### Manual Verification
|
||||
```bash
|
||||
# Check time synchronization
|
||||
python check_time.py
|
||||
|
||||
# Test timezone functions
|
||||
python test_timezone.py
|
||||
|
||||
# View system time status
|
||||
timedatectl status
|
||||
```
|
||||
|
||||
### API Endpoints
|
||||
```bash
|
||||
# System status includes time info
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# Example response includes:
|
||||
{
|
||||
"system_started": true,
|
||||
"uptime_seconds": 3600,
|
||||
"timestamp": "2025-07-25T21:32:41-04:00"
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Current Status
|
||||
|
||||
### Time Synchronization
|
||||
- ✅ **System Timezone**: America/New_York (EDT)
|
||||
- ✅ **NTP Sync**: Active and synchronized
|
||||
- ✅ **Time Accuracy**: Within 0.1 seconds of atomic time
|
||||
- ✅ **DST Support**: Automatic EST/EDT switching
|
||||
|
||||
### Application Integration
|
||||
- ✅ **Recording Timestamps**: Atlanta time zone
|
||||
- ✅ **Log Timestamps**: Timezone-aware logging
|
||||
- ✅ **API Responses**: ISO format with timezone
|
||||
- ✅ **File Naming**: Consistent Atlanta time format
|
||||
|
||||
### Monitoring
|
||||
- ✅ **Startup Verification**: Time sync checked on boot
|
||||
- ✅ **Continuous Monitoring**: Built-in sync status tracking
|
||||
- ✅ **Error Detection**: Alerts for time drift issues
|
||||
- ✅ **Manual Tools**: On-demand verification scripts
|
||||
|
||||
## 🔍 Technical Details
|
||||
|
||||
### Timezone Configuration
|
||||
```json
|
||||
{
|
||||
"system": {
|
||||
"timezone": "America/New_York"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Time Sources
|
||||
1. **Primary**: NIST atomic clock (time.nist.gov)
|
||||
2. **Secondary**: NTP pool servers (pool.ntp.org)
|
||||
3. **Backup**: Google/Cloudflare time servers
|
||||
4. **Fallback**: Local system clock
|
||||
|
||||
### File Naming Convention
|
||||
```
|
||||
Pattern: {camera_name}_recording_{YYYYMMDD_HHMMSS}.avi
|
||||
Example: camera1_recording_20250725_213241.avi
|
||||
Timezone: Always Atlanta local time (EST/EDT)
|
||||
```
|
||||
|
||||
## 🎯 Benefits
|
||||
|
||||
### For Operations
|
||||
- **Consistent Timestamps**: All recordings use Atlanta time
|
||||
- **Easy Correlation**: Timestamps match local business hours
|
||||
- **Automatic DST**: No manual timezone adjustments needed
|
||||
- **Reliable Sync**: Multiple time sources ensure accuracy
|
||||
|
||||
### For Analysis
|
||||
- **Local Time Context**: Recordings timestamped in business timezone
|
||||
- **Accurate Sequencing**: Precise timing for event correlation
|
||||
- **Standard Format**: Consistent naming across all recordings
|
||||
- **Audit Trail**: Complete time synchronization logging
|
||||
|
||||
### For Integration
|
||||
- **Dashboard Ready**: Timezone-aware API responses
|
||||
- **Database Compatible**: ISO format timestamps with timezone
|
||||
- **Log Analysis**: Structured time information in logs
|
||||
- **Monitoring**: Built-in time sync health checks
|
||||
|
||||
## 🔧 Maintenance
|
||||
|
||||
### Regular Checks
|
||||
The system automatically:
|
||||
- Verifies time sync on startup
|
||||
- Logs time synchronization status
|
||||
- Monitors for time drift
|
||||
- Alerts on sync failures
|
||||
|
||||
### Manual Maintenance
|
||||
```bash
|
||||
# Force time sync
|
||||
sudo systemctl restart systemd-timesyncd
|
||||
|
||||
# Check NTP status
|
||||
timedatectl show-timesync --all
|
||||
|
||||
# Verify timezone
|
||||
timedatectl status
|
||||
```
|
||||
|
||||
## 📈 Next Steps
|
||||
|
||||
The time synchronization is now fully operational. The system will:
|
||||
|
||||
1. **Automatically maintain** accurate Atlanta time
|
||||
2. **Generate timestamped recordings** with local time
|
||||
3. **Monitor sync status** and alert on issues
|
||||
4. **Provide timezone-aware** API responses for dashboard integration
|
||||
|
||||
All recording files will now have accurate Atlanta timestamps, making it easy to correlate with local business operations and machine schedules.
|
||||
|
||||
---
|
||||
|
||||
**Time Sync Status**: ✅ **SYNCHRONIZED**
|
||||
**Timezone**: ✅ **America/New_York (EDT)**
|
||||
**Accuracy**: ✅ **±0.1 seconds**
|
||||
**Ready for Production**: ✅ **YES**
|
||||
191
camera-management-api/docs/legacy/VIDEO_RECORDER_README.md
Normal file
191
camera-management-api/docs/legacy/VIDEO_RECORDER_README.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Camera Video Recorder
|
||||
|
||||
A Python script for recording videos from GigE cameras using the provided SDK with custom exposure and gain settings.
|
||||
|
||||
## Features
|
||||
|
||||
- **List all available cameras** - Automatically detects and displays all connected cameras
|
||||
- **Custom camera settings** - Set exposure time to 1ms and gain to 3.5x (or custom values)
|
||||
- **Video recording** - Record videos in AVI format with timestamp filenames
|
||||
- **Live preview** - Test camera functionality with live preview mode
|
||||
- **Interactive menu** - User-friendly menu system for all operations
|
||||
- **Automatic cleanup** - Proper resource management and cleanup
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.x
|
||||
- OpenCV (`cv2`)
|
||||
- NumPy
|
||||
- Camera SDK (mvsdk) - included in `python demo` directory
|
||||
- GigE camera connected to the system
|
||||
|
||||
## Installation
|
||||
|
||||
1. Ensure your GigE camera is connected and properly configured
|
||||
2. Make sure the `python demo` directory with `mvsdk.py` is present
|
||||
3. Install required Python packages:
|
||||
```bash
|
||||
pip install opencv-python numpy
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Run the script:
|
||||
```bash
|
||||
python camera_video_recorder.py
|
||||
```
|
||||
|
||||
The script will:
|
||||
1. Display a welcome message and feature overview
|
||||
2. List all available cameras
|
||||
3. Let you select a camera (if multiple are available)
|
||||
4. Allow you to set custom exposure and gain values
|
||||
5. Present an interactive menu with options
|
||||
|
||||
### Menu Options
|
||||
|
||||
1. **Start Recording** - Begin video recording with timestamp filename
|
||||
2. **List Camera Info** - Display detailed camera information
|
||||
3. **Test Camera (Live Preview)** - View live camera feed without recording
|
||||
4. **Exit** - Clean up and exit the program
|
||||
|
||||
### Default Settings
|
||||
|
||||
- **Exposure Time**: 1.0ms (1000 microseconds)
|
||||
- **Gain**: 3.5x
|
||||
- **Video Format**: AVI with XVID codec
|
||||
- **Frame Rate**: 30 FPS
|
||||
- **Output Directory**: `videos/` (created automatically)
|
||||
|
||||
### Recording Controls
|
||||
|
||||
- **Start Recording**: Select option 1 from the menu
|
||||
- **Stop Recording**: Press 'q' in the preview window
|
||||
- **Video Files**: Saved as `videos/camera_recording_YYYYMMDD_HHMMSS.avi`
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
camera_video_recorder.py # Main script
|
||||
python demo/
|
||||
mvsdk.py # Camera SDK wrapper
|
||||
(other demo files)
|
||||
videos/ # Output directory (created automatically)
|
||||
camera_recording_*.avi # Recorded video files
|
||||
```
|
||||
|
||||
## Script Features
|
||||
|
||||
### CameraVideoRecorder Class
|
||||
|
||||
- `list_cameras()` - Enumerate and display available cameras
|
||||
- `initialize_camera()` - Set up camera with custom exposure and gain
|
||||
- `start_recording()` - Initialize video writer and begin recording
|
||||
- `stop_recording()` - Stop recording and save video file
|
||||
- `record_loop()` - Main recording loop with live preview
|
||||
- `cleanup()` - Proper resource cleanup
|
||||
|
||||
### Key Functions
|
||||
|
||||
- **Camera Detection**: Automatically finds all connected GigE cameras
|
||||
- **Settings Validation**: Checks and clamps exposure/gain values to camera limits
|
||||
- **Frame Processing**: Handles both monochrome and color cameras
|
||||
- **Windows Compatibility**: Handles frame flipping for Windows systems
|
||||
- **Error Handling**: Comprehensive error handling and user feedback
|
||||
|
||||
## Example Output
|
||||
|
||||
```
|
||||
Camera Video Recorder
|
||||
====================
|
||||
This script allows you to:
|
||||
- List all available cameras
|
||||
- Record videos with custom exposure (1ms) and gain (3.5x) settings
|
||||
- Save videos with timestamps
|
||||
- Stop recording anytime with 'q' key
|
||||
|
||||
Found 1 camera(s):
|
||||
0: GigE Camera Model (GigE) - SN: 12345678
|
||||
|
||||
Using camera: GigE Camera Model
|
||||
|
||||
Camera Settings:
|
||||
Enter exposure time in ms (default 1.0): 1.0
|
||||
Enter gain value (default 3.5): 3.5
|
||||
|
||||
Initializing camera with:
|
||||
- Exposure: 1.0ms
|
||||
- Gain: 3.5x
|
||||
|
||||
Camera type: Color
|
||||
Set exposure time: 1000.0μs
|
||||
Set analog gain: 3.50x (range: 1.00 - 16.00)
|
||||
Camera started successfully
|
||||
|
||||
==================================================
|
||||
Camera Video Recorder Menu
|
||||
==================================================
|
||||
1. Start Recording
|
||||
2. List Camera Info
|
||||
3. Test Camera (Live Preview)
|
||||
4. Exit
|
||||
|
||||
Select option (1-4): 1
|
||||
|
||||
Started recording to: videos/camera_recording_20241223_143022.avi
|
||||
Frame size: (1920, 1080), FPS: 30.0
|
||||
Press 'q' to stop recording...
|
||||
Recording... Press 'q' in the preview window to stop
|
||||
|
||||
Recording stopped!
|
||||
Saved: videos/camera_recording_20241223_143022.avi
|
||||
Frames recorded: 450
|
||||
Duration: 15.2 seconds
|
||||
Average FPS: 29.6
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **"No cameras found!"**
|
||||
- Check camera connection
|
||||
- Verify camera power
|
||||
- Ensure network configuration for GigE cameras
|
||||
|
||||
2. **"SDK initialization failed"**
|
||||
- Verify `python demo/mvsdk.py` exists
|
||||
- Check camera drivers are installed
|
||||
|
||||
3. **"Camera initialization failed"**
|
||||
- Camera may be in use by another application
|
||||
- Try disconnecting and reconnecting the camera
|
||||
|
||||
4. **Recording issues**
|
||||
- Ensure sufficient disk space
|
||||
- Check write permissions in the output directory
|
||||
|
||||
### Performance Tips
|
||||
|
||||
- Close other applications using the camera
|
||||
- Ensure adequate system resources (CPU, RAM)
|
||||
- Use SSD storage for better write performance
|
||||
- Adjust frame rate if experiencing dropped frames
|
||||
|
||||
## Customization
|
||||
|
||||
You can modify the script to:
|
||||
- Change video codec (currently XVID)
|
||||
- Adjust target frame rate
|
||||
- Modify output filename format
|
||||
- Add additional camera settings
|
||||
- Change preview window size
|
||||
|
||||
## Notes
|
||||
|
||||
- Videos are saved in the `videos/` directory with timestamp filenames
|
||||
- The script handles both monochrome and color cameras automatically
|
||||
- Frame flipping is handled automatically for Windows systems
|
||||
- All resources are properly cleaned up on exit
|
||||
Reference in New Issue
Block a user