feat: Add CameraPreviewModal component for live camera streaming
feat: Implement useAuth hook for user authentication management feat: Create useAutoRecording hook for managing automatic recording functionality feat: Develop AutoRecordingManager to handle automatic recording based on MQTT events test: Add test script to verify camera configuration API fix test: Create HTML page for testing camera configuration API and auto-recording fields
This commit is contained in:
175
API Documentations/AI_AGENT_INSTRUCTIONS.md
Normal file
175
API Documentations/AI_AGENT_INSTRUCTIONS.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Instructions for AI Agent: Auto-Recording Feature Integration
|
||||
|
||||
## 🎯 Task Overview
|
||||
Update the React application to support the new auto-recording feature that has been added to the USDA Vision Camera System backend.
|
||||
|
||||
## 📋 What You Need to Know
|
||||
|
||||
### System Context
|
||||
- **Camera 1** monitors the **vibratory conveyor** (conveyor/cracker cam)
|
||||
- **Camera 2** monitors the **blower separator** machine
|
||||
- Auto-recording automatically starts when machines turn ON and stops when they turn OFF
|
||||
- The system includes retry logic for failed recording attempts
|
||||
- Manual recording always takes precedence over auto-recording
|
||||
|
||||
### New Backend Capabilities
|
||||
The backend now supports:
|
||||
1. **Automatic recording** triggered by MQTT machine state changes
|
||||
2. **Retry mechanism** for failed recording attempts (configurable retries and delays)
|
||||
3. **Status tracking** for auto-recording state, failures, and attempts
|
||||
4. **API endpoints** for enabling/disabling and monitoring auto-recording
|
||||
|
||||
## 🔧 Required React App Changes
|
||||
|
||||
### 1. Update TypeScript Interfaces
|
||||
|
||||
Add these new fields to existing `CameraStatusResponse`:
|
||||
```typescript
|
||||
interface CameraStatusResponse {
|
||||
// ... existing fields
|
||||
auto_recording_enabled: boolean;
|
||||
auto_recording_active: boolean;
|
||||
auto_recording_failure_count: number;
|
||||
auto_recording_last_attempt?: string;
|
||||
auto_recording_last_error?: string;
|
||||
}
|
||||
```
|
||||
|
||||
Add 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[];
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Add New API Endpoints
|
||||
|
||||
```typescript
|
||||
// Enable auto-recording for a camera
|
||||
POST /cameras/{camera_name}/auto-recording/enable
|
||||
|
||||
// Disable auto-recording for a camera
|
||||
POST /cameras/{camera_name}/auto-recording/disable
|
||||
|
||||
// Get overall auto-recording system status
|
||||
GET /auto-recording/status
|
||||
```
|
||||
|
||||
### 3. UI Components to Add/Update
|
||||
|
||||
#### Camera Status Display
|
||||
- Add auto-recording status badge/indicator
|
||||
- Show auto-recording enabled/disabled state
|
||||
- Display failure count if > 0
|
||||
- Show last error message if any
|
||||
- Distinguish between manual and auto-recording states
|
||||
|
||||
#### Auto-Recording Controls
|
||||
- Toggle switch to enable/disable auto-recording per camera
|
||||
- System-wide auto-recording status display
|
||||
- Retry queue information
|
||||
- Machine state correlation display
|
||||
|
||||
#### Error Handling
|
||||
- Clear display of auto-recording failures
|
||||
- Retry attempt information
|
||||
- Last attempt timestamp
|
||||
- Quick retry/reset actions
|
||||
|
||||
### 4. Visual Design Guidelines
|
||||
|
||||
**Status Priority (highest to lowest):**
|
||||
1. Manual Recording (red/prominent) - user initiated
|
||||
2. Auto-Recording Active (green) - machine ON, recording
|
||||
3. Auto-Recording Enabled (blue) - ready but machine OFF
|
||||
4. Auto-Recording Disabled (gray) - feature disabled
|
||||
|
||||
**Machine Correlation:**
|
||||
- Show machine name next to camera (e.g., "Vibratory Conveyor", "Blower Separator")
|
||||
- Display machine ON/OFF status
|
||||
- Alert if machine is ON but auto-recording failed
|
||||
|
||||
## 🎨 Specific Implementation Tasks
|
||||
|
||||
### Task 1: Update Camera Cards
|
||||
- Add auto-recording status indicators
|
||||
- Add enable/disable toggle controls
|
||||
- Show machine state correlation
|
||||
- Display failure information when relevant
|
||||
|
||||
### Task 2: Create Auto-Recording Dashboard
|
||||
- Overall system status
|
||||
- List of enabled cameras
|
||||
- Active retry queue display
|
||||
- Recent events/errors
|
||||
|
||||
### Task 3: Update Recording Status Logic
|
||||
- Distinguish between manual and auto-recording
|
||||
- Show appropriate controls based on recording type
|
||||
- Handle manual override scenarios
|
||||
|
||||
### Task 4: Add Error Handling
|
||||
- Display auto-recording failures clearly
|
||||
- Show retry attempts and timing
|
||||
- Provide manual retry options
|
||||
|
||||
## 📱 User Experience Requirements
|
||||
|
||||
### Key Behaviors
|
||||
1. **Non-Intrusive:** Auto-recording status shouldn't clutter the main interface
|
||||
2. **Clear Hierarchy:** Manual controls should be more prominent than auto-recording
|
||||
3. **Informative:** Users should understand why recording started/stopped
|
||||
4. **Actionable:** Clear options to enable/disable or retry failed attempts
|
||||
|
||||
### Mobile Considerations
|
||||
- Auto-recording controls should work well on mobile
|
||||
- Status information should be readable on small screens
|
||||
- Consider collapsible sections for detailed information
|
||||
|
||||
## 🔍 Testing Requirements
|
||||
|
||||
Ensure the React app correctly handles:
|
||||
- [ ] Toggling auto-recording on/off per camera
|
||||
- [ ] Displaying real-time status updates
|
||||
- [ ] Showing error states and retry information
|
||||
- [ ] Manual recording override scenarios
|
||||
- [ ] Machine state changes and correlation
|
||||
- [ ] Mobile interface functionality
|
||||
|
||||
## 📚 Reference Files
|
||||
|
||||
Key files to review for implementation details:
|
||||
- `AUTO_RECORDING_FEATURE_GUIDE.md` - Comprehensive technical details
|
||||
- `api-endpoints.http` - API endpoint documentation
|
||||
- `config.json` - Configuration structure
|
||||
- `usda_vision_system/api/models.py` - Response type definitions
|
||||
|
||||
## 🎯 Success Criteria
|
||||
|
||||
The React app should:
|
||||
1. **Display** auto-recording status for each camera clearly
|
||||
2. **Allow** users to enable/disable auto-recording per camera
|
||||
3. **Show** machine state correlation and recording triggers
|
||||
4. **Handle** error states and retry scenarios gracefully
|
||||
5. **Maintain** existing manual recording functionality
|
||||
6. **Provide** clear visual hierarchy between manual and auto-recording
|
||||
|
||||
## 💡 Implementation Tips
|
||||
|
||||
1. **Start Small:** Begin with basic status display, then add controls
|
||||
2. **Use Existing Patterns:** Follow the current app's design patterns
|
||||
3. **Test Incrementally:** Test each feature as you add it
|
||||
4. **Consider State Management:** Update your state management to handle new data
|
||||
5. **Mobile First:** Ensure mobile usability from the start
|
||||
|
||||
The goal is to seamlessly integrate auto-recording capabilities while maintaining the existing user experience and adding valuable automation features for the camera operators.
|
||||
595
API Documentations/AI_INTEGRATION_GUIDE.md
Normal file
595
API Documentations/AI_INTEGRATION_GUIDE.md
Normal file
@@ -0,0 +1,595 @@
|
||||
# 🤖 AI Integration Guide: USDA Vision Camera Streaming for React Projects
|
||||
|
||||
This guide is specifically designed for AI assistants to understand and implement the USDA Vision Camera streaming functionality in React applications.
|
||||
|
||||
## 📋 System Overview
|
||||
|
||||
The USDA Vision Camera system provides live video streaming through REST API endpoints. The streaming uses MJPEG format which is natively supported by HTML `<img>` tags and can be easily integrated into React components.
|
||||
|
||||
### Key Characteristics:
|
||||
- **Base URL**: `http://vision:8000` (production) or `http://localhost:8000` (development)
|
||||
- **Stream Format**: MJPEG (Motion JPEG)
|
||||
- **Content-Type**: `multipart/x-mixed-replace; boundary=frame`
|
||||
- **Authentication**: None (add if needed for production)
|
||||
- **CORS**: Enabled for all origins (configure for production)
|
||||
|
||||
### Base URL Configuration:
|
||||
- **Production**: `http://vision:8000` (requires hostname setup)
|
||||
- **Development**: `http://localhost:8000` (local testing)
|
||||
- **Custom IP**: `http://192.168.1.100:8000` (replace with actual IP)
|
||||
- **Custom hostname**: Configure DNS or /etc/hosts as needed
|
||||
|
||||
## 🔌 API Endpoints Reference
|
||||
|
||||
### 1. Get Camera List
|
||||
```http
|
||||
GET /cameras
|
||||
```
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"camera1": {
|
||||
"name": "camera1",
|
||||
"status": "connected",
|
||||
"is_recording": false,
|
||||
"last_checked": "2025-01-28T10:30:00",
|
||||
"device_info": {...}
|
||||
},
|
||||
"camera2": {...}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Start Camera Stream
|
||||
```http
|
||||
POST /cameras/{camera_name}/start-stream
|
||||
```
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Started streaming for camera camera1"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Stop Camera Stream
|
||||
```http
|
||||
POST /cameras/{camera_name}/stop-stream
|
||||
```
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"message": "Stopped streaming for camera camera1"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Live Video Stream
|
||||
```http
|
||||
GET /cameras/{camera_name}/stream
|
||||
```
|
||||
**Response:** MJPEG video stream
|
||||
**Usage:** Set as `src` attribute of HTML `<img>` element
|
||||
|
||||
## ⚛️ React Integration Examples
|
||||
|
||||
### Basic Camera Stream Component
|
||||
|
||||
```jsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
const CameraStream = ({ cameraName, apiBaseUrl = 'http://vision:8000' }) => {
|
||||
const [isStreaming, setIsStreaming] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const startStream = async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/start-stream`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setIsStreaming(true);
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
setError(errorData.detail || 'Failed to start stream');
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Network error: ${err.message}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const stopStream = async () => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/stop-stream`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setIsStreaming(false);
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
setError(errorData.detail || 'Failed to stop stream');
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Network error: ${err.message}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="camera-stream">
|
||||
<h3>Camera: {cameraName}</h3>
|
||||
|
||||
{/* Video Stream */}
|
||||
<div className="stream-container">
|
||||
{isStreaming ? (
|
||||
<img
|
||||
src={`${apiBaseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`}
|
||||
alt={`${cameraName} live stream`}
|
||||
style={{
|
||||
width: '100%',
|
||||
maxWidth: '640px',
|
||||
height: 'auto',
|
||||
border: '2px solid #ddd',
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
onError={() => setError('Stream connection lost')}
|
||||
/>
|
||||
) : (
|
||||
<div style={{
|
||||
width: '100%',
|
||||
maxWidth: '640px',
|
||||
height: '360px',
|
||||
backgroundColor: '#f0f0f0',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '2px solid #ddd',
|
||||
borderRadius: '8px',
|
||||
}}>
|
||||
<span>No Stream Active</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Controls */}
|
||||
<div className="stream-controls" style={{ marginTop: '10px' }}>
|
||||
<button
|
||||
onClick={startStream}
|
||||
disabled={loading || isStreaming}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
marginRight: '8px',
|
||||
backgroundColor: '#28a745',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: loading ? 'not-allowed' : 'pointer',
|
||||
}}
|
||||
>
|
||||
{loading ? 'Loading...' : 'Start Stream'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={stopStream}
|
||||
disabled={loading || !isStreaming}
|
||||
style={{
|
||||
padding: '8px 16px',
|
||||
backgroundColor: '#dc3545',
|
||||
color: 'white',
|
||||
border: 'none',
|
||||
borderRadius: '4px',
|
||||
cursor: loading ? 'not-allowed' : 'pointer',
|
||||
}}
|
||||
>
|
||||
{loading ? 'Loading...' : 'Stop Stream'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Error Display */}
|
||||
{error && (
|
||||
<div style={{
|
||||
marginTop: '10px',
|
||||
padding: '8px',
|
||||
backgroundColor: '#f8d7da',
|
||||
color: '#721c24',
|
||||
border: '1px solid #f5c6cb',
|
||||
borderRadius: '4px',
|
||||
}}>
|
||||
Error: {error}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CameraStream;
|
||||
```
|
||||
|
||||
### Multi-Camera Dashboard Component
|
||||
|
||||
```jsx
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import CameraStream from './CameraStream';
|
||||
|
||||
const CameraDashboard = ({ apiBaseUrl = 'http://vision:8000' }) => {
|
||||
const [cameras, setCameras] = useState({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchCameras();
|
||||
|
||||
// Refresh camera status every 30 seconds
|
||||
const interval = setInterval(fetchCameras, 30000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const fetchCameras = async () => {
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras`);
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
setCameras(data);
|
||||
setError(null);
|
||||
} else {
|
||||
setError('Failed to fetch cameras');
|
||||
}
|
||||
} catch (err) {
|
||||
setError(`Network error: ${err.message}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
return <div>Loading cameras...</div>;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div style={{ color: 'red', padding: '20px' }}>
|
||||
Error: {error}
|
||||
<button onClick={fetchCameras} style={{ marginLeft: '10px' }}>
|
||||
Retry
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="camera-dashboard">
|
||||
<h1>USDA Vision Camera Dashboard</h1>
|
||||
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(auto-fit, minmax(400px, 1fr))',
|
||||
gap: '20px',
|
||||
padding: '20px',
|
||||
}}>
|
||||
{Object.entries(cameras).map(([cameraName, cameraInfo]) => (
|
||||
<div key={cameraName} style={{
|
||||
border: '1px solid #ddd',
|
||||
borderRadius: '8px',
|
||||
padding: '15px',
|
||||
backgroundColor: '#f9f9f9',
|
||||
}}>
|
||||
<CameraStream
|
||||
cameraName={cameraName}
|
||||
apiBaseUrl={apiBaseUrl}
|
||||
/>
|
||||
|
||||
{/* Camera Status */}
|
||||
<div style={{ marginTop: '10px', fontSize: '14px' }}>
|
||||
<div>Status: <strong>{cameraInfo.status}</strong></div>
|
||||
<div>Recording: <strong>{cameraInfo.is_recording ? 'Yes' : 'No'}</strong></div>
|
||||
<div>Last Checked: {new Date(cameraInfo.last_checked).toLocaleString()}</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CameraDashboard;
|
||||
```
|
||||
|
||||
### Custom Hook for Camera Management
|
||||
|
||||
```jsx
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
|
||||
const useCameraStream = (cameraName, apiBaseUrl = 'http://vision:8000') => {
|
||||
const [isStreaming, setIsStreaming] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
const startStream = useCallback(async () => {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/start-stream`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setIsStreaming(true);
|
||||
return { success: true };
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
const errorMsg = errorData.detail || 'Failed to start stream';
|
||||
setError(errorMsg);
|
||||
return { success: false, error: errorMsg };
|
||||
}
|
||||
} catch (err) {
|
||||
const errorMsg = `Network error: ${err.message}`;
|
||||
setError(errorMsg);
|
||||
return { success: false, error: errorMsg };
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [cameraName, apiBaseUrl]);
|
||||
|
||||
const stopStream = useCallback(async () => {
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/stop-stream`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
setIsStreaming(false);
|
||||
return { success: true };
|
||||
} else {
|
||||
const errorData = await response.json();
|
||||
const errorMsg = errorData.detail || 'Failed to stop stream';
|
||||
setError(errorMsg);
|
||||
return { success: false, error: errorMsg };
|
||||
}
|
||||
} catch (err) {
|
||||
const errorMsg = `Network error: ${err.message}`;
|
||||
setError(errorMsg);
|
||||
return { success: false, error: errorMsg };
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [cameraName, apiBaseUrl]);
|
||||
|
||||
const getStreamUrl = useCallback(() => {
|
||||
return `${apiBaseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`;
|
||||
}, [cameraName, apiBaseUrl]);
|
||||
|
||||
return {
|
||||
isStreaming,
|
||||
loading,
|
||||
error,
|
||||
startStream,
|
||||
stopStream,
|
||||
getStreamUrl,
|
||||
};
|
||||
};
|
||||
|
||||
export default useCameraStream;
|
||||
```
|
||||
|
||||
## 🎨 Styling with Tailwind CSS
|
||||
|
||||
```jsx
|
||||
const CameraStreamTailwind = ({ cameraName }) => {
|
||||
const { isStreaming, loading, error, startStream, stopStream, getStreamUrl } = useCameraStream(cameraName);
|
||||
|
||||
return (
|
||||
<div className="bg-white rounded-lg shadow-md p-6">
|
||||
<h3 className="text-lg font-semibold mb-4">Camera: {cameraName}</h3>
|
||||
|
||||
{/* Stream Container */}
|
||||
<div className="relative mb-4">
|
||||
{isStreaming ? (
|
||||
<img
|
||||
src={getStreamUrl()}
|
||||
alt={`${cameraName} live stream`}
|
||||
className="w-full max-w-2xl h-auto border-2 border-gray-300 rounded-lg"
|
||||
onError={() => setError('Stream connection lost')}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full max-w-2xl h-64 bg-gray-100 border-2 border-gray-300 rounded-lg flex items-center justify-center">
|
||||
<span className="text-gray-500">No Stream Active</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Controls */}
|
||||
<div className="flex gap-2 mb-4">
|
||||
<button
|
||||
onClick={startStream}
|
||||
disabled={loading || isStreaming}
|
||||
className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ? 'Loading...' : 'Start Stream'}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={stopStream}
|
||||
disabled={loading || !isStreaming}
|
||||
className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
{loading ? 'Loading...' : 'Stop Stream'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Error Display */}
|
||||
{error && (
|
||||
<div className="p-3 bg-red-100 border border-red-400 text-red-700 rounded">
|
||||
Error: {error}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## 🔧 Configuration Options
|
||||
|
||||
### Environment Variables (.env)
|
||||
```env
|
||||
# Production configuration (using 'vision' hostname)
|
||||
REACT_APP_CAMERA_API_URL=http://vision:8000
|
||||
REACT_APP_STREAM_REFRESH_INTERVAL=30000
|
||||
REACT_APP_STREAM_TIMEOUT=10000
|
||||
|
||||
# Development configuration (using localhost)
|
||||
# REACT_APP_CAMERA_API_URL=http://localhost:8000
|
||||
|
||||
# Custom IP configuration
|
||||
# REACT_APP_CAMERA_API_URL=http://192.168.1.100:8000
|
||||
```
|
||||
|
||||
### API Configuration
|
||||
```javascript
|
||||
const apiConfig = {
|
||||
baseUrl: process.env.REACT_APP_CAMERA_API_URL || 'http://vision:8000',
|
||||
timeout: parseInt(process.env.REACT_APP_STREAM_TIMEOUT) || 10000,
|
||||
refreshInterval: parseInt(process.env.REACT_APP_STREAM_REFRESH_INTERVAL) || 30000,
|
||||
};
|
||||
```
|
||||
|
||||
### Hostname Setup Guide
|
||||
```bash
|
||||
# Option 1: Add to /etc/hosts (Linux/Mac)
|
||||
echo "127.0.0.1 vision" | sudo tee -a /etc/hosts
|
||||
|
||||
# Option 2: Add to hosts file (Windows)
|
||||
# Add to C:\Windows\System32\drivers\etc\hosts:
|
||||
# 127.0.0.1 vision
|
||||
|
||||
# Option 3: Configure DNS
|
||||
# Point 'vision' hostname to your server's IP address
|
||||
|
||||
# Verify hostname resolution
|
||||
ping vision
|
||||
```
|
||||
|
||||
## 🚨 Important Implementation Notes
|
||||
|
||||
### 1. MJPEG Stream Handling
|
||||
- Use HTML `<img>` tag with `src` pointing to stream endpoint
|
||||
- Add timestamp query parameter to prevent caching: `?t=${Date.now()}`
|
||||
- Handle `onError` event for connection issues
|
||||
|
||||
### 2. Error Handling
|
||||
- Network errors (fetch failures)
|
||||
- HTTP errors (4xx, 5xx responses)
|
||||
- Stream connection errors (img onError)
|
||||
- Timeout handling for long requests
|
||||
|
||||
### 3. Performance Considerations
|
||||
- Streams consume bandwidth continuously
|
||||
- Stop streams when components unmount
|
||||
- Limit concurrent streams based on system capacity
|
||||
- Consider lazy loading for multiple cameras
|
||||
|
||||
### 4. State Management
|
||||
- Track streaming state per camera
|
||||
- Handle loading states during API calls
|
||||
- Manage error states with user feedback
|
||||
- Refresh camera list periodically
|
||||
|
||||
## 📱 Mobile Considerations
|
||||
|
||||
```jsx
|
||||
// Responsive design for mobile
|
||||
const mobileStyles = {
|
||||
container: {
|
||||
padding: '10px',
|
||||
maxWidth: '100vw',
|
||||
},
|
||||
stream: {
|
||||
width: '100%',
|
||||
maxWidth: '100vw',
|
||||
height: 'auto',
|
||||
},
|
||||
controls: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '8px',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## 🧪 Testing Integration
|
||||
|
||||
```javascript
|
||||
// Test API connectivity
|
||||
const testConnection = async () => {
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/health`);
|
||||
return response.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// Test camera availability
|
||||
const testCamera = async (cameraName) => {
|
||||
try {
|
||||
const response = await fetch(`${apiBaseUrl}/cameras/${cameraName}/test-connection`, {
|
||||
method: 'POST',
|
||||
});
|
||||
return response.ok;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 📁 Additional Files for AI Integration
|
||||
|
||||
### TypeScript Definitions
|
||||
- `camera-api.types.ts` - Complete TypeScript definitions for all API types
|
||||
- `streaming-api.http` - REST Client file with all streaming endpoints
|
||||
- `STREAMING_GUIDE.md` - Comprehensive user guide for streaming functionality
|
||||
|
||||
### Quick Integration Checklist for AI Assistants
|
||||
|
||||
1. **Copy TypeScript types** from `camera-api.types.ts`
|
||||
2. **Use API endpoints** from `streaming-api.http`
|
||||
3. **Implement error handling** as shown in examples
|
||||
4. **Add CORS configuration** if needed for production
|
||||
5. **Test with multiple cameras** using provided examples
|
||||
|
||||
### Key Integration Points
|
||||
|
||||
- **Stream URL Format**: `${baseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`
|
||||
- **Start Stream**: `POST /cameras/{name}/start-stream`
|
||||
- **Stop Stream**: `POST /cameras/{name}/stop-stream`
|
||||
- **Camera List**: `GET /cameras`
|
||||
- **Error Handling**: Always wrap in try-catch blocks
|
||||
- **Loading States**: Implement for better UX
|
||||
|
||||
### Production Considerations
|
||||
|
||||
- Configure CORS for specific origins
|
||||
- Add authentication if required
|
||||
- Implement rate limiting
|
||||
- Monitor system resources with multiple streams
|
||||
- Add reconnection logic for network issues
|
||||
|
||||
This documentation provides everything an AI assistant needs to integrate the USDA Vision Camera streaming functionality into React applications, including complete code examples, error handling, and best practices.
|
||||
260
API Documentations/AUTO_RECORDING_FEATURE_GUIDE.md
Normal file
260
API Documentations/AUTO_RECORDING_FEATURE_GUIDE.md
Normal file
@@ -0,0 +1,260 @@
|
||||
# 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.
|
||||
|
||||
## 📋 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!
|
||||
455
API Documentations/CAMERA_CONFIG_API.md
Normal file
455
API Documentations/CAMERA_CONFIG_API.md
Normal file
@@ -0,0 +1,455 @@
|
||||
# 🎛️ Camera Configuration API Guide
|
||||
|
||||
This guide explains how to configure camera settings via API endpoints, including all the advanced settings from your config.json.
|
||||
|
||||
## 📋 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`
|
||||
- **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`
|
||||
- **System**: `machine_topic`, `storage_path`, `enabled`, `bit_depth`
|
||||
|
||||
### 🤖 **Auto-Recording**
|
||||
|
||||
- **Auto-Recording**: `auto_record_on_machine_start` - When enabled, the camera automatically starts recording when MQTT messages indicate the associated machine turns on, and stops recording when it turns off
|
||||
|
||||
## 🔌 API Endpoints
|
||||
|
||||
### 1. Get Camera Configuration
|
||||
|
||||
```http
|
||||
GET /cameras/{camera_name}/config
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "vibratory_conveyor",
|
||||
"storage_path": "/storage/camera1",
|
||||
"enabled": true,
|
||||
"auto_record_on_machine_start": false,
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.5,
|
||||
"target_fps": 0,
|
||||
"sharpness": 120,
|
||||
"contrast": 110,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": true,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": true,
|
||||
"color_temperature_preset": 0,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Update Camera Configuration
|
||||
|
||||
```http
|
||||
PUT /cameras/{camera_name}/config
|
||||
Content-Type: application/json
|
||||
```
|
||||
|
||||
**Request Body (all fields optional):**
|
||||
|
||||
```json
|
||||
{
|
||||
"auto_record_on_machine_start": true,
|
||||
"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,
|
||||
"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"]
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
### 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) |
|
||||
|
||||
### 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>
|
||||
|
||||
{/* 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>
|
||||
|
||||
{/* 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!
|
||||
870
API Documentations/README.md
Normal file
870
API Documentations/README.md
Normal file
@@ -0,0 +1,870 @@
|
||||
# USDA Vision Camera System
|
||||
|
||||
A comprehensive system for monitoring machines via MQTT and automatically recording video from GigE cameras when machines are active. Designed for Atlanta, Georgia operations with proper timezone synchronization.
|
||||
|
||||
## 🎯 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 an Atlanta timezone timestamp.
|
||||
|
||||
### Key Features
|
||||
|
||||
- **🔄 MQTT Integration**: Listens to multiple machine state topics
|
||||
- **📹 Automatic Recording**: Starts/stops recording based on machine states
|
||||
- **📷 GigE Camera Support**: Uses camera SDK 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
|
||||
- **🕐 Timezone Sync**: Proper time synchronization for Atlanta, Georgia
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
USDA-Vision-Cameras/
|
||||
├── README.md # Main documentation (this file)
|
||||
├── main.py # System entry point
|
||||
├── config.json # System configuration
|
||||
├── requirements.txt # Python dependencies
|
||||
├── pyproject.toml # UV package configuration
|
||||
├── start_system.sh # Startup script
|
||||
├── setup_timezone.sh # Time sync setup
|
||||
├── camera_preview.html # Web camera preview interface
|
||||
├── 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
|
||||
├── tests/ # Organized test files
|
||||
│ ├── api/ # API-related tests
|
||||
│ ├── camera/ # Camera functionality tests
|
||||
│ ├── core/ # Core system tests
|
||||
│ ├── mqtt/ # MQTT integration tests
|
||||
│ ├── recording/ # Recording feature tests
|
||||
│ ├── storage/ # Storage management tests
|
||||
│ ├── integration/ # System integration tests
|
||||
│ └── legacy_tests/ # Archived development files
|
||||
├── docs/ # Organized documentation
|
||||
│ ├── api/ # API documentation
|
||||
│ ├── features/ # Feature-specific guides
|
||||
│ ├── guides/ # User and setup guides
|
||||
│ └── legacy/ # Legacy documentation
|
||||
├── ai_agent/ # AI agent resources
|
||||
│ ├── guides/ # AI-specific instructions
|
||||
│ ├── examples/ # Demo scripts and notebooks
|
||||
│ └── references/ # API references and types
|
||||
├── Camera/ # Camera data directory
|
||||
└── storage/ # Recording storage (created at runtime)
|
||||
├── camera1/ # Camera 1 recordings
|
||||
└── camera2/ # Camera 2 recordings
|
||||
```
|
||||
|
||||
## 🏗️ 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 │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 📋 Prerequisites
|
||||
|
||||
### Hardware Requirements
|
||||
- GigE cameras compatible with camera SDK library
|
||||
- Network connection to MQTT broker
|
||||
- Sufficient storage space for video recordings
|
||||
|
||||
### Software Requirements
|
||||
- **Python 3.11+**
|
||||
- **uv package manager** (recommended) or pip
|
||||
- **MQTT broker** (e.g., Mosquitto, Home Assistant)
|
||||
- **Linux system** (tested on Ubuntu/Debian)
|
||||
|
||||
### Network Requirements
|
||||
- Access to MQTT broker
|
||||
- GigE cameras on network
|
||||
- Internet access for time synchronization (optional but recommended)
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
### 1. Clone the Repository
|
||||
```bash
|
||||
git clone https://github.com/your-username/USDA-Vision-Cameras.git
|
||||
cd USDA-Vision-Cameras
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
Using uv (recommended):
|
||||
```bash
|
||||
# Install uv if not already installed
|
||||
curl -LsSf https://astral.sh/uv/install.sh | sh
|
||||
|
||||
# Install dependencies
|
||||
uv sync
|
||||
```
|
||||
|
||||
Using pip:
|
||||
```bash
|
||||
# Create virtual environment
|
||||
python -m venv .venv
|
||||
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 3. Setup GigE Camera Library
|
||||
Ensure the `camera_sdk` directory contains the mvsdk library for your GigE cameras. This should include:
|
||||
- `mvsdk.py` - Python SDK wrapper
|
||||
- Camera driver libraries
|
||||
- Any camera-specific configuration files
|
||||
|
||||
### 4. Configure Storage Directory
|
||||
```bash
|
||||
# Create storage directory (adjust path as needed)
|
||||
mkdir -p ./storage
|
||||
# Or for system-wide storage:
|
||||
# sudo mkdir -p /storage && sudo chown $USER:$USER /storage
|
||||
```
|
||||
|
||||
### 5. Setup Time Synchronization (Recommended)
|
||||
```bash
|
||||
# Run timezone setup for Atlanta, Georgia
|
||||
./setup_timezone.sh
|
||||
```
|
||||
|
||||
### 6. Configure the System
|
||||
Edit `config.json` to match your setup:
|
||||
```json
|
||||
{
|
||||
"mqtt": {
|
||||
"broker_host": "192.168.1.110",
|
||||
"broker_port": 1883,
|
||||
"topics": {
|
||||
"machine1": "vision/machine1/state",
|
||||
"machine2": "vision/machine2/state"
|
||||
}
|
||||
},
|
||||
"cameras": [
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "machine1",
|
||||
"storage_path": "./storage/camera1",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### MQTT Configuration
|
||||
```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"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Camera Configuration
|
||||
```json
|
||||
{
|
||||
"cameras": [
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "vibratory_conveyor",
|
||||
"storage_path": "./storage/camera1",
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.5,
|
||||
"target_fps": 3.0,
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### System Configuration
|
||||
```json
|
||||
{
|
||||
"system": {
|
||||
"camera_check_interval_seconds": 2,
|
||||
"log_level": "INFO",
|
||||
"api_host": "0.0.0.0",
|
||||
"api_port": 8000,
|
||||
"enable_api": true,
|
||||
"timezone": "America/New_York"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎮 Usage
|
||||
|
||||
### Quick Start
|
||||
```bash
|
||||
# Test the system
|
||||
python test_system.py
|
||||
|
||||
# Start the system
|
||||
python main.py
|
||||
|
||||
# Or use the startup script
|
||||
./start_system.sh
|
||||
```
|
||||
|
||||
### Command Line Options
|
||||
```bash
|
||||
# Custom configuration file
|
||||
python main.py --config my_config.json
|
||||
|
||||
# Debug mode
|
||||
python main.py --log-level DEBUG
|
||||
|
||||
# Help
|
||||
python main.py --help
|
||||
```
|
||||
|
||||
### Verify Installation
|
||||
```bash
|
||||
# Run system tests
|
||||
python test_system.py
|
||||
|
||||
# Check time synchronization
|
||||
python check_time.py
|
||||
|
||||
# Test timezone functions
|
||||
python test_timezone.py
|
||||
```
|
||||
|
||||
## 🌐 API Usage
|
||||
|
||||
The system provides a comprehensive REST API for monitoring and control.
|
||||
|
||||
> **📚 Complete API Documentation**: See [docs/API_DOCUMENTATION.md](docs/API_DOCUMENTATION.md) for the full API reference including all endpoints, request/response models, examples, and recent enhancements.
|
||||
>
|
||||
> **⚡ Quick Reference**: See [docs/API_QUICK_REFERENCE.md](docs/API_QUICK_REFERENCE.md) for commonly used endpoints with curl examples.
|
||||
|
||||
### Starting the API Server
|
||||
The API server starts automatically with the main system on port 8000:
|
||||
```bash
|
||||
python main.py
|
||||
# API available at: http://localhost:8000
|
||||
```
|
||||
|
||||
### 🚀 New API Features
|
||||
|
||||
#### Enhanced Recording Control
|
||||
- **Dynamic camera settings**: Set exposure, gain, FPS per recording
|
||||
- **Automatic datetime prefixes**: All filenames get timestamp prefixes
|
||||
- **Auto-recording management**: Enable/disable per camera via API
|
||||
|
||||
#### Advanced Camera Configuration
|
||||
- **Real-time settings**: Update image quality without restart
|
||||
- **Live streaming**: MJPEG streams for web integration
|
||||
- **Recovery operations**: Reconnect, reset, reinitialize cameras
|
||||
|
||||
#### Comprehensive Monitoring
|
||||
- **MQTT event history**: Track machine state changes
|
||||
- **Storage statistics**: Monitor disk usage and file counts
|
||||
- **WebSocket updates**: Real-time system notifications
|
||||
|
||||
### Core Endpoints
|
||||
|
||||
#### System Status
|
||||
```bash
|
||||
# Get overall system status
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# Response example:
|
||||
{
|
||||
"system_started": true,
|
||||
"mqtt_connected": true,
|
||||
"machines": {
|
||||
"vibratory_conveyor": {"state": "on", "last_updated": "2025-07-25T21:30:00-04:00"}
|
||||
},
|
||||
"cameras": {
|
||||
"camera1": {"status": "available", "is_recording": true}
|
||||
},
|
||||
"active_recordings": 1,
|
||||
"uptime_seconds": 3600
|
||||
}
|
||||
```
|
||||
|
||||
#### Machine Status
|
||||
```bash
|
||||
# Get all machine states
|
||||
curl http://localhost:8000/machines
|
||||
|
||||
# Response example:
|
||||
{
|
||||
"vibratory_conveyor": {
|
||||
"name": "vibratory_conveyor",
|
||||
"state": "on",
|
||||
"last_updated": "2025-07-25T21:30:00-04:00",
|
||||
"mqtt_topic": "vision/vibratory_conveyor/state"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Camera Status
|
||||
```bash
|
||||
# Get all camera statuses
|
||||
curl http://localhost:8000/cameras
|
||||
|
||||
# Get specific camera status
|
||||
curl http://localhost:8000/cameras/camera1
|
||||
|
||||
# Response example:
|
||||
{
|
||||
"name": "camera1",
|
||||
"status": "available",
|
||||
"is_recording": false,
|
||||
"last_checked": "2025-07-25T21:30:00-04:00",
|
||||
"device_info": {
|
||||
"friendly_name": "Blower-Yield-Cam",
|
||||
"serial_number": "054012620023"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Manual Recording Control
|
||||
```bash
|
||||
# Start recording manually
|
||||
curl -X POST http://localhost:8000/cameras/camera1/start-recording \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"camera_name": "camera1", "filename": "manual_test.avi"}'
|
||||
|
||||
# Stop recording manually
|
||||
curl -X POST http://localhost:8000/cameras/camera1/stop-recording
|
||||
|
||||
# Response example:
|
||||
{
|
||||
"success": true,
|
||||
"message": "Recording started for camera1",
|
||||
"filename": "camera1_manual_20250725_213000.avi"
|
||||
}
|
||||
```
|
||||
|
||||
#### Storage Management
|
||||
```bash
|
||||
# Get storage statistics
|
||||
curl http://localhost:8000/storage/stats
|
||||
|
||||
# Get recording files list
|
||||
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}'
|
||||
```
|
||||
|
||||
### WebSocket Real-time Updates
|
||||
```javascript
|
||||
// Connect to WebSocket for real-time updates
|
||||
const ws = new WebSocket('ws://localhost:8000/ws');
|
||||
|
||||
ws.onmessage = function(event) {
|
||||
const update = JSON.parse(event.data);
|
||||
console.log('Real-time update:', update);
|
||||
|
||||
// Handle different event types
|
||||
if (update.event_type === 'machine_state_changed') {
|
||||
console.log(`Machine ${update.data.machine_name} is now ${update.data.state}`);
|
||||
} else if (update.event_type === 'recording_started') {
|
||||
console.log(`Recording started: ${update.data.filename}`);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Integration Examples
|
||||
|
||||
#### Python Integration
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
# System status check
|
||||
response = requests.get('http://localhost:8000/system/status')
|
||||
status = response.json()
|
||||
print(f"System running: {status['system_started']}")
|
||||
|
||||
# Start recording
|
||||
recording_data = {"camera_name": "camera1"}
|
||||
response = requests.post(
|
||||
'http://localhost:8000/cameras/camera1/start-recording',
|
||||
headers={'Content-Type': 'application/json'},
|
||||
data=json.dumps(recording_data)
|
||||
)
|
||||
result = response.json()
|
||||
print(f"Recording started: {result['success']}")
|
||||
```
|
||||
|
||||
#### JavaScript/React Integration
|
||||
```javascript
|
||||
// React hook for system status
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
function useSystemStatus() {
|
||||
const [status, setStatus] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchStatus = async () => {
|
||||
try {
|
||||
const response = await fetch('http://localhost:8000/system/status');
|
||||
const data = await response.json();
|
||||
setStatus(data);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch status:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchStatus();
|
||||
const interval = setInterval(fetchStatus, 5000); // Update every 5 seconds
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Usage in component
|
||||
function Dashboard() {
|
||||
const systemStatus = useSystemStatus();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>USDA Vision System</h1>
|
||||
{systemStatus && (
|
||||
<div>
|
||||
<p>Status: {systemStatus.system_started ? 'Running' : 'Stopped'}</p>
|
||||
<p>MQTT: {systemStatus.mqtt_connected ? 'Connected' : 'Disconnected'}</p>
|
||||
<p>Active Recordings: {systemStatus.active_recordings}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
#### Supabase Integration
|
||||
```javascript
|
||||
// Store recording metadata in Supabase
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
||||
|
||||
// Function to sync recording data
|
||||
async function syncRecordingData() {
|
||||
try {
|
||||
// Get recordings from vision system
|
||||
const response = await fetch('http://localhost:8000/storage/files', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ limit: 100 })
|
||||
});
|
||||
const { files } = await response.json();
|
||||
|
||||
// Store in Supabase
|
||||
for (const file of files) {
|
||||
await supabase.from('recordings').upsert({
|
||||
filename: file.filename,
|
||||
camera_name: file.camera_name,
|
||||
start_time: file.start_time,
|
||||
duration_seconds: file.duration_seconds,
|
||||
file_size_bytes: file.file_size_bytes
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Sync failed:', error);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📁 File Organization
|
||||
|
||||
The system organizes recordings in a structured format:
|
||||
|
||||
```
|
||||
storage/
|
||||
├── camera1/
|
||||
│ ├── camera1_recording_20250725_213000.avi
|
||||
│ ├── camera1_recording_20250725_214500.avi
|
||||
│ └── camera1_manual_20250725_220000.avi
|
||||
├── camera2/
|
||||
│ ├── camera2_recording_20250725_213005.avi
|
||||
│ └── camera2_recording_20250725_214505.avi
|
||||
└── file_index.json
|
||||
```
|
||||
|
||||
### Filename Convention
|
||||
- **Format**: `{camera_name}_{type}_{YYYYMMDD_HHMMSS}.avi`
|
||||
- **Timezone**: Atlanta local time (EST/EDT)
|
||||
- **Examples**:
|
||||
- `camera1_recording_20250725_213000.avi` - Automatic recording
|
||||
- `camera1_manual_20250725_220000.avi` - Manual recording
|
||||
|
||||
## 🔍 Monitoring and Logging
|
||||
|
||||
### Log Files
|
||||
- **Main Log**: `usda_vision_system.log` (rotated automatically)
|
||||
- **Console Output**: Colored, real-time status updates
|
||||
- **Component Logs**: Separate log levels for different components
|
||||
|
||||
### Log Levels
|
||||
```bash
|
||||
# Debug mode (verbose)
|
||||
python main.py --log-level DEBUG
|
||||
|
||||
# Info mode (default)
|
||||
python main.py --log-level INFO
|
||||
|
||||
# Warning mode (errors and warnings only)
|
||||
python main.py --log-level WARNING
|
||||
```
|
||||
|
||||
### Performance Monitoring
|
||||
The system tracks:
|
||||
- Startup times
|
||||
- Recording session metrics
|
||||
- MQTT message processing rates
|
||||
- Camera status check intervals
|
||||
- API response times
|
||||
|
||||
### Health Checks
|
||||
```bash
|
||||
# API health check
|
||||
curl http://localhost:8000/health
|
||||
|
||||
# System status
|
||||
curl http://localhost:8000/system/status
|
||||
|
||||
# Time synchronization
|
||||
python check_time.py
|
||||
```
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Common Issues and Solutions
|
||||
|
||||
#### 1. Camera Not Found
|
||||
**Problem**: `Camera discovery failed` or `No cameras found`
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Check camera connections
|
||||
ping 192.168.1.165 # Replace with your camera IP
|
||||
|
||||
# Verify camera SDK library
|
||||
ls -la "camera_sdk/"
|
||||
# Should contain mvsdk.py and related files
|
||||
|
||||
# Test camera discovery manually
|
||||
python -c "
|
||||
import sys; sys.path.append('./camera_sdk')
|
||||
import mvsdk
|
||||
devices = mvsdk.CameraEnumerateDevice()
|
||||
print(f'Found {len(devices)} cameras')
|
||||
for i, dev in enumerate(devices):
|
||||
print(f'Camera {i}: {dev.GetFriendlyName()}')
|
||||
"
|
||||
|
||||
# Check camera permissions
|
||||
sudo chmod 666 /dev/video* # If using USB cameras
|
||||
```
|
||||
|
||||
#### 2. MQTT Connection Failed
|
||||
**Problem**: `MQTT connection failed` or `MQTT disconnected`
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Test MQTT broker connectivity
|
||||
ping 192.168.1.110 # Replace with your broker IP
|
||||
telnet 192.168.1.110 1883 # Test port connectivity
|
||||
|
||||
# Test MQTT manually
|
||||
mosquitto_sub -h 192.168.1.110 -t "vision/+/state" -v
|
||||
|
||||
# Check credentials in config.json
|
||||
{
|
||||
"mqtt": {
|
||||
"broker_host": "192.168.1.110",
|
||||
"broker_port": 1883,
|
||||
"username": "your_username", # Add if required
|
||||
"password": "your_password" # Add if required
|
||||
}
|
||||
}
|
||||
|
||||
# Check firewall
|
||||
sudo ufw status
|
||||
sudo ufw allow 1883 # Allow MQTT port
|
||||
```
|
||||
|
||||
#### 3. Recording Fails
|
||||
**Problem**: `Failed to start recording` or `Camera initialization failed`
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Check storage permissions
|
||||
ls -la storage/
|
||||
chmod 755 storage/
|
||||
chmod 755 storage/camera*/
|
||||
|
||||
# Check available disk space
|
||||
df -h storage/
|
||||
|
||||
# Test camera initialization
|
||||
python -c "
|
||||
import sys; sys.path.append('./camera_sdk')
|
||||
import mvsdk
|
||||
devices = mvsdk.CameraEnumerateDevice()
|
||||
if devices:
|
||||
try:
|
||||
hCamera = mvsdk.CameraInit(devices[0], -1, -1)
|
||||
print('Camera initialized successfully')
|
||||
mvsdk.CameraUnInit(hCamera)
|
||||
except Exception as e:
|
||||
print(f'Camera init failed: {e}')
|
||||
"
|
||||
|
||||
# Check if camera is busy
|
||||
lsof | grep video # Check what's using cameras
|
||||
```
|
||||
|
||||
#### 4. API Server Won't Start
|
||||
**Problem**: `Failed to start API server` or `Port already in use`
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Check if port 8000 is in use
|
||||
netstat -tlnp | grep 8000
|
||||
lsof -i :8000
|
||||
|
||||
# Kill process using port 8000
|
||||
sudo kill -9 $(lsof -t -i:8000)
|
||||
|
||||
# Use different port in config.json
|
||||
{
|
||||
"system": {
|
||||
"api_port": 8001 # Change port
|
||||
}
|
||||
}
|
||||
|
||||
# Check firewall
|
||||
sudo ufw allow 8000
|
||||
```
|
||||
|
||||
#### 5. Time Synchronization Issues
|
||||
**Problem**: `Time is NOT synchronized` or time drift warnings
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Check time sync status
|
||||
timedatectl status
|
||||
|
||||
# Force time sync
|
||||
sudo systemctl restart systemd-timesyncd
|
||||
sudo timedatectl set-ntp true
|
||||
|
||||
# Manual time sync
|
||||
sudo ntpdate -s time.nist.gov
|
||||
|
||||
# Check timezone
|
||||
timedatectl list-timezones | grep New_York
|
||||
sudo timedatectl set-timezone America/New_York
|
||||
|
||||
# Verify with system
|
||||
python check_time.py
|
||||
```
|
||||
|
||||
#### 6. Storage Issues
|
||||
**Problem**: `Permission denied` or `No space left on device`
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Check disk space
|
||||
df -h
|
||||
du -sh storage/
|
||||
|
||||
# Fix permissions
|
||||
sudo chown -R $USER:$USER storage/
|
||||
chmod -R 755 storage/
|
||||
|
||||
# Clean up old files
|
||||
python -c "
|
||||
from usda_vision_system.storage.manager import StorageManager
|
||||
from usda_vision_system.core.config import Config
|
||||
from usda_vision_system.core.state_manager import StateManager
|
||||
config = Config()
|
||||
state_manager = StateManager()
|
||||
storage = StorageManager(config, state_manager)
|
||||
result = storage.cleanup_old_files(7) # Clean files older than 7 days
|
||||
print(f'Cleaned {result[\"files_removed\"]} files')
|
||||
"
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug mode for detailed troubleshooting:
|
||||
```bash
|
||||
# Start with debug logging
|
||||
python main.py --log-level DEBUG
|
||||
|
||||
# Check specific component logs
|
||||
tail -f usda_vision_system.log | grep "camera"
|
||||
tail -f usda_vision_system.log | grep "mqtt"
|
||||
tail -f usda_vision_system.log | grep "ERROR"
|
||||
```
|
||||
|
||||
### System Health Check
|
||||
|
||||
Run comprehensive system diagnostics:
|
||||
```bash
|
||||
# Full system test
|
||||
python test_system.py
|
||||
|
||||
# Individual component tests
|
||||
python test_timezone.py
|
||||
python check_time.py
|
||||
|
||||
# API health check
|
||||
curl http://localhost:8000/health
|
||||
curl http://localhost:8000/system/status
|
||||
```
|
||||
|
||||
### Log Analysis
|
||||
|
||||
Common log patterns to look for:
|
||||
```bash
|
||||
# MQTT connection issues
|
||||
grep "MQTT" usda_vision_system.log | grep -E "(ERROR|WARNING)"
|
||||
|
||||
# Camera problems
|
||||
grep "camera" usda_vision_system.log | grep -E "(ERROR|failed)"
|
||||
|
||||
# Recording issues
|
||||
grep "recording" usda_vision_system.log | grep -E "(ERROR|failed)"
|
||||
|
||||
# Time sync problems
|
||||
grep -E "(time|sync)" usda_vision_system.log | grep -E "(ERROR|WARNING)"
|
||||
```
|
||||
|
||||
### Getting Help
|
||||
|
||||
If you encounter issues not covered here:
|
||||
|
||||
1. **Check Logs**: Always start with `usda_vision_system.log`
|
||||
2. **Run Tests**: Use `python test_system.py` to identify problems
|
||||
3. **Check Configuration**: Verify `config.json` settings
|
||||
4. **Test Components**: Use individual test scripts
|
||||
5. **Check Dependencies**: Ensure all required packages are installed
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
For better performance:
|
||||
```bash
|
||||
# Reduce camera check interval (in config.json)
|
||||
{
|
||||
"system": {
|
||||
"camera_check_interval_seconds": 5 # Increase from 2 to 5
|
||||
}
|
||||
}
|
||||
|
||||
# Optimize recording settings
|
||||
{
|
||||
"cameras": [
|
||||
{
|
||||
"target_fps": 2.0, # Reduce FPS for smaller files
|
||||
"exposure_ms": 2.0 # Adjust exposure as needed
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Enable log rotation
|
||||
{
|
||||
"system": {
|
||||
"log_level": "INFO" # Reduce from DEBUG to INFO
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
### Development Setup
|
||||
```bash
|
||||
# Clone repository
|
||||
git clone https://github.com/your-username/USDA-Vision-Cameras.git
|
||||
cd USDA-Vision-Cameras
|
||||
|
||||
# Install development dependencies
|
||||
uv sync --dev
|
||||
|
||||
# Run tests
|
||||
python test_system.py
|
||||
python test_timezone.py
|
||||
```
|
||||
|
||||
### Project Structure
|
||||
```
|
||||
usda_vision_system/
|
||||
├── core/ # Core functionality (config, state, events, logging)
|
||||
├── mqtt/ # MQTT client and message handlers
|
||||
├── camera/ # Camera management, monitoring, recording
|
||||
├── storage/ # File management and organization
|
||||
├── api/ # FastAPI server and WebSocket support
|
||||
└── main.py # Application coordinator
|
||||
```
|
||||
|
||||
### Adding Features
|
||||
1. **New Camera Types**: 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`
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is developed for USDA research purposes.
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
For technical support:
|
||||
1. Check the troubleshooting section above
|
||||
2. Review logs in `usda_vision_system.log`
|
||||
3. Run system diagnostics with `python test_system.py`
|
||||
4. Check API health at `http://localhost:8000/health`
|
||||
|
||||
---
|
||||
|
||||
**System Status**: ✅ **READY FOR PRODUCTION**
|
||||
**Time Sync**: ✅ **ATLANTA, GEORGIA (EDT/EST)**
|
||||
**API Server**: ✅ **http://localhost:8000**
|
||||
**Documentation**: ✅ **COMPLETE**
|
||||
240
API Documentations/STREAMING_GUIDE.md
Normal file
240
API Documentations/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!**
|
||||
367
API Documentations/camera-api.types.ts
Normal file
367
API Documentations/camera-api.types.ts
Normal file
@@ -0,0 +1,367 @@
|
||||
/**
|
||||
* TypeScript definitions for USDA Vision Camera System API
|
||||
*
|
||||
* This file provides complete type definitions for AI assistants
|
||||
* to integrate the camera streaming functionality into React/TypeScript projects.
|
||||
*/
|
||||
|
||||
// =============================================================================
|
||||
// BASE CONFIGURATION
|
||||
// =============================================================================
|
||||
|
||||
export interface ApiConfig {
|
||||
baseUrl: string;
|
||||
timeout?: number;
|
||||
refreshInterval?: number;
|
||||
}
|
||||
|
||||
export const defaultApiConfig: ApiConfig = {
|
||||
baseUrl: 'http://vision:8000', // Production default, change to 'http://localhost:8000' for development
|
||||
timeout: 10000,
|
||||
refreshInterval: 30000,
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// CAMERA TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraDeviceInfo {
|
||||
friendly_name?: string;
|
||||
port_type?: string;
|
||||
serial_number?: string;
|
||||
device_index?: number;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface CameraInfo {
|
||||
name: string;
|
||||
status: 'connected' | 'disconnected' | 'error' | 'not_found' | 'available';
|
||||
is_recording: boolean;
|
||||
last_checked: string; // ISO date string
|
||||
last_error?: string | null;
|
||||
device_info?: CameraDeviceInfo;
|
||||
current_recording_file?: string | null;
|
||||
recording_start_time?: string | null; // ISO date string
|
||||
}
|
||||
|
||||
export interface CameraListResponse {
|
||||
[cameraName: string]: CameraInfo;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// STREAMING TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface StreamStartRequest {
|
||||
// No body required - camera name is in URL path
|
||||
}
|
||||
|
||||
export interface StreamStartResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface StreamStopRequest {
|
||||
// No body required - camera name is in URL path
|
||||
}
|
||||
|
||||
export interface StreamStopResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface StreamStatus {
|
||||
isStreaming: boolean;
|
||||
streamUrl?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// RECORDING TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface StartRecordingRequest {
|
||||
filename?: string;
|
||||
exposure_ms?: number;
|
||||
gain?: number;
|
||||
fps?: number;
|
||||
}
|
||||
|
||||
export interface StartRecordingResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
filename?: string;
|
||||
}
|
||||
|
||||
export interface StopRecordingResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SYSTEM TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface SystemStatusResponse {
|
||||
status: string;
|
||||
uptime: string;
|
||||
api_server_running: boolean;
|
||||
camera_manager_running: boolean;
|
||||
mqtt_client_connected: boolean;
|
||||
total_cameras: number;
|
||||
active_recordings: number;
|
||||
active_streams?: number;
|
||||
}
|
||||
|
||||
export interface HealthResponse {
|
||||
status: 'healthy' | 'unhealthy';
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ERROR TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface ApiError {
|
||||
detail: string;
|
||||
status_code?: number;
|
||||
}
|
||||
|
||||
export interface StreamError extends Error {
|
||||
type: 'network' | 'api' | 'stream' | 'timeout';
|
||||
cameraName: string;
|
||||
originalError?: Error;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// HOOK TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface UseCameraStreamResult {
|
||||
isStreaming: boolean;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
startStream: () => Promise<{ success: boolean; error?: string }>;
|
||||
stopStream: () => Promise<{ success: boolean; error?: string }>;
|
||||
getStreamUrl: () => string;
|
||||
refreshStream: () => void;
|
||||
}
|
||||
|
||||
export interface UseCameraListResult {
|
||||
cameras: CameraListResponse;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
refreshCameras: () => Promise<void>;
|
||||
}
|
||||
|
||||
export interface UseCameraRecordingResult {
|
||||
isRecording: boolean;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
currentFile: string | null;
|
||||
startRecording: (options?: StartRecordingRequest) => Promise<{ success: boolean; error?: string }>;
|
||||
stopRecording: () => Promise<{ success: boolean; error?: string }>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMPONENT PROPS TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraStreamProps {
|
||||
cameraName: string;
|
||||
apiConfig?: ApiConfig;
|
||||
autoStart?: boolean;
|
||||
onStreamStart?: (cameraName: string) => void;
|
||||
onStreamStop?: (cameraName: string) => void;
|
||||
onError?: (error: StreamError) => void;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface CameraDashboardProps {
|
||||
apiConfig?: ApiConfig;
|
||||
cameras?: string[]; // If provided, only show these cameras
|
||||
showRecordingControls?: boolean;
|
||||
showStreamingControls?: boolean;
|
||||
refreshInterval?: number;
|
||||
onCameraSelect?: (cameraName: string) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface CameraControlsProps {
|
||||
cameraName: string;
|
||||
apiConfig?: ApiConfig;
|
||||
showRecording?: boolean;
|
||||
showStreaming?: boolean;
|
||||
onAction?: (action: 'start-stream' | 'stop-stream' | 'start-recording' | 'stop-recording', cameraName: string) => void;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// API CLIENT TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraApiClient {
|
||||
// System endpoints
|
||||
getHealth(): Promise<HealthResponse>;
|
||||
getSystemStatus(): Promise<SystemStatusResponse>;
|
||||
|
||||
// Camera endpoints
|
||||
getCameras(): Promise<CameraListResponse>;
|
||||
getCameraStatus(cameraName: string): Promise<CameraInfo>;
|
||||
testCameraConnection(cameraName: string): Promise<{ success: boolean; message: string }>;
|
||||
|
||||
// Streaming endpoints
|
||||
startStream(cameraName: string): Promise<StreamStartResponse>;
|
||||
stopStream(cameraName: string): Promise<StreamStopResponse>;
|
||||
getStreamUrl(cameraName: string): string;
|
||||
|
||||
// Recording endpoints
|
||||
startRecording(cameraName: string, options?: StartRecordingRequest): Promise<StartRecordingResponse>;
|
||||
stopRecording(cameraName: string): Promise<StopRecordingResponse>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// UTILITY TYPES
|
||||
// =============================================================================
|
||||
|
||||
export type CameraAction = 'start-stream' | 'stop-stream' | 'start-recording' | 'stop-recording' | 'test-connection';
|
||||
|
||||
export interface CameraActionResult {
|
||||
success: boolean;
|
||||
message: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface StreamingState {
|
||||
[cameraName: string]: {
|
||||
isStreaming: boolean;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
lastStarted?: Date;
|
||||
};
|
||||
}
|
||||
|
||||
export interface RecordingState {
|
||||
[cameraName: string]: {
|
||||
isRecording: boolean;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
currentFile: string | null;
|
||||
startTime?: Date;
|
||||
};
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EVENT TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraEvent {
|
||||
type: 'stream-started' | 'stream-stopped' | 'stream-error' | 'recording-started' | 'recording-stopped' | 'recording-error';
|
||||
cameraName: string;
|
||||
timestamp: Date;
|
||||
data?: any;
|
||||
}
|
||||
|
||||
export type CameraEventHandler = (event: CameraEvent) => void;
|
||||
|
||||
// =============================================================================
|
||||
// CONFIGURATION TYPES
|
||||
// =============================================================================
|
||||
|
||||
export interface StreamConfig {
|
||||
fps: number;
|
||||
quality: number; // 1-100
|
||||
timeout: number;
|
||||
retryAttempts: number;
|
||||
retryDelay: number;
|
||||
}
|
||||
|
||||
export interface CameraStreamConfig extends StreamConfig {
|
||||
cameraName: string;
|
||||
autoReconnect: boolean;
|
||||
maxReconnectAttempts: number;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// CONTEXT TYPES (for React Context)
|
||||
// =============================================================================
|
||||
|
||||
export interface CameraContextValue {
|
||||
cameras: CameraListResponse;
|
||||
streamingState: StreamingState;
|
||||
recordingState: RecordingState;
|
||||
apiClient: CameraApiClient;
|
||||
|
||||
// Actions
|
||||
startStream: (cameraName: string) => Promise<CameraActionResult>;
|
||||
stopStream: (cameraName: string) => Promise<CameraActionResult>;
|
||||
startRecording: (cameraName: string, options?: StartRecordingRequest) => Promise<CameraActionResult>;
|
||||
stopRecording: (cameraName: string) => Promise<CameraActionResult>;
|
||||
refreshCameras: () => Promise<void>;
|
||||
|
||||
// State
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// EXAMPLE USAGE TYPES
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Example usage in React component:
|
||||
*
|
||||
* ```typescript
|
||||
* import { CameraStreamProps, UseCameraStreamResult } from './camera-api.types';
|
||||
*
|
||||
* const CameraStream: React.FC<CameraStreamProps> = ({
|
||||
* cameraName,
|
||||
* apiConfig = defaultApiConfig,
|
||||
* autoStart = false,
|
||||
* onStreamStart,
|
||||
* onStreamStop,
|
||||
* onError
|
||||
* }) => {
|
||||
* const {
|
||||
* isStreaming,
|
||||
* loading,
|
||||
* error,
|
||||
* startStream,
|
||||
* stopStream,
|
||||
* getStreamUrl
|
||||
* }: UseCameraStreamResult = useCameraStream(cameraName, apiConfig);
|
||||
*
|
||||
* // Component implementation...
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example API client usage:
|
||||
*
|
||||
* ```typescript
|
||||
* const apiClient: CameraApiClient = new CameraApiClientImpl(defaultApiConfig);
|
||||
*
|
||||
* // Start streaming
|
||||
* const result = await apiClient.startStream('camera1');
|
||||
* if (result.success) {
|
||||
* const streamUrl = apiClient.getStreamUrl('camera1');
|
||||
* // Use streamUrl in img tag
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
|
||||
/**
|
||||
* Example hook usage:
|
||||
*
|
||||
* ```typescript
|
||||
* const MyComponent = () => {
|
||||
* const { cameras, loading, error, refreshCameras } = useCameraList();
|
||||
* const { isStreaming, startStream, stopStream } = useCameraStream('camera1');
|
||||
*
|
||||
* // Component logic...
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
|
||||
export default {};
|
||||
336
API Documentations/camera_preview.html
Normal file
336
API Documentations/camera_preview.html
Normal file
@@ -0,0 +1,336 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>USDA Vision Camera Live Preview</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.camera-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
||||
gap: 20px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.camera-card {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
.camera-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.camera-stream {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 2px solid #ddd;
|
||||
border-radius: 4px;
|
||||
background-color: #000;
|
||||
min-height: 200px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.camera-controls {
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #6c757d;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: #545b62;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-success:hover {
|
||||
background-color: #1e7e34;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-danger:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-top: 10px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
border: 1px solid #c3e6cb;
|
||||
}
|
||||
|
||||
.status-error {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.status-info {
|
||||
background-color: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border: 1px solid #bee5eb;
|
||||
}
|
||||
|
||||
.system-info {
|
||||
margin-top: 30px;
|
||||
padding: 15px;
|
||||
background-color: #e9ecef;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.system-info h3 {
|
||||
margin-top: 0;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.api-info {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
color: #6c757d;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🎥 USDA Vision Camera Live Preview</h1>
|
||||
|
||||
<div class="camera-grid" id="cameraGrid">
|
||||
<!-- Camera cards will be dynamically generated -->
|
||||
</div>
|
||||
|
||||
<div class="system-info">
|
||||
<h3>📡 System Information</h3>
|
||||
<div id="systemStatus">Loading system status...</div>
|
||||
|
||||
<h3>🔗 API Endpoints</h3>
|
||||
<div class="api-info">
|
||||
<p><strong>Live Stream:</strong> GET /cameras/{camera_name}/stream</p>
|
||||
<p><strong>Start Stream:</strong> POST /cameras/{camera_name}/start-stream</p>
|
||||
<p><strong>Stop Stream:</strong> POST /cameras/{camera_name}/stop-stream</p>
|
||||
<p><strong>Camera Status:</strong> GET /cameras</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const API_BASE = 'http://vision:8000';
|
||||
let cameras = {};
|
||||
|
||||
// Initialize the page
|
||||
async function init() {
|
||||
await loadCameras();
|
||||
await loadSystemStatus();
|
||||
|
||||
// Refresh status every 5 seconds
|
||||
setInterval(loadSystemStatus, 5000);
|
||||
}
|
||||
|
||||
// Load camera information
|
||||
async function loadCameras() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/cameras`);
|
||||
const data = await response.json();
|
||||
cameras = data;
|
||||
renderCameras();
|
||||
} catch (error) {
|
||||
console.error('Error loading cameras:', error);
|
||||
showError('Failed to load camera information');
|
||||
}
|
||||
}
|
||||
|
||||
// Load system status
|
||||
async function loadSystemStatus() {
|
||||
try {
|
||||
const response = await fetch(`${API_BASE}/system/status`);
|
||||
const data = await response.json();
|
||||
|
||||
const statusDiv = document.getElementById('systemStatus');
|
||||
statusDiv.innerHTML = `
|
||||
<p><strong>System:</strong> ${data.status}</p>
|
||||
<p><strong>Uptime:</strong> ${data.uptime}</p>
|
||||
<p><strong>API Server:</strong> ${data.api_server_running ? '✅ Running' : '❌ Stopped'}</p>
|
||||
<p><strong>Camera Manager:</strong> ${data.camera_manager_running ? '✅ Running' : '❌ Stopped'}</p>
|
||||
<p><strong>MQTT Client:</strong> ${data.mqtt_client_connected ? '✅ Connected' : '❌ Disconnected'}</p>
|
||||
`;
|
||||
} catch (error) {
|
||||
console.error('Error loading system status:', error);
|
||||
document.getElementById('systemStatus').innerHTML = '<p style="color: red;">Failed to load system status</p>';
|
||||
}
|
||||
}
|
||||
|
||||
// Render camera cards
|
||||
function renderCameras() {
|
||||
const grid = document.getElementById('cameraGrid');
|
||||
grid.innerHTML = '';
|
||||
|
||||
for (const [cameraName, cameraInfo] of Object.entries(cameras)) {
|
||||
const card = createCameraCard(cameraName, cameraInfo);
|
||||
grid.appendChild(card);
|
||||
}
|
||||
}
|
||||
|
||||
// Create a camera card
|
||||
function createCameraCard(cameraName, cameraInfo) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'camera-card';
|
||||
card.innerHTML = `
|
||||
<div class="camera-title">${cameraName}</div>
|
||||
<img class="camera-stream" id="stream-${cameraName}"
|
||||
src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZGRkIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPk5vIFN0cmVhbTwvdGV4dD48L3N2Zz4="
|
||||
alt="Camera Stream">
|
||||
<div class="camera-controls">
|
||||
<button class="btn btn-success" onclick="startStream('${cameraName}')">Start Stream</button>
|
||||
<button class="btn btn-danger" onclick="stopStream('${cameraName}')">Stop Stream</button>
|
||||
<button class="btn btn-secondary" onclick="refreshStream('${cameraName}')">Refresh</button>
|
||||
</div>
|
||||
<div class="status status-info" id="status-${cameraName}">
|
||||
Status: ${cameraInfo.status} | Recording: ${cameraInfo.is_recording ? 'Yes' : 'No'}
|
||||
</div>
|
||||
`;
|
||||
return card;
|
||||
}
|
||||
|
||||
// Start streaming for a camera
|
||||
async function startStream(cameraName) {
|
||||
try {
|
||||
updateStatus(cameraName, 'Starting stream...', 'info');
|
||||
|
||||
// Start the stream
|
||||
const response = await fetch(`${API_BASE}/cameras/${cameraName}/start-stream`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Set the stream source
|
||||
const streamImg = document.getElementById(`stream-${cameraName}`);
|
||||
streamImg.src = `${API_BASE}/cameras/${cameraName}/stream?t=${Date.now()}`;
|
||||
|
||||
updateStatus(cameraName, 'Stream started successfully', 'success');
|
||||
} else {
|
||||
const error = await response.text();
|
||||
updateStatus(cameraName, `Failed to start stream: ${error}`, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error starting stream:', error);
|
||||
updateStatus(cameraName, `Error starting stream: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Stop streaming for a camera
|
||||
async function stopStream(cameraName) {
|
||||
try {
|
||||
updateStatus(cameraName, 'Stopping stream...', 'info');
|
||||
|
||||
const response = await fetch(`${API_BASE}/cameras/${cameraName}/stop-stream`, {
|
||||
method: 'POST'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Clear the stream source
|
||||
const streamImg = document.getElementById(`stream-${cameraName}`);
|
||||
streamImg.src = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSIjZGRkIi8+PHRleHQgeD0iNTAlIiB5PSI1MCUiIGZvbnQtZmFtaWx5PSJBcmlhbCIgZm9udC1zaXplPSIxNCIgZmlsbD0iIzk5OSIgdGV4dC1hbmNob3I9Im1pZGRsZSIgZHk9Ii4zZW0iPk5vIFN0cmVhbTwvdGV4dD48L3N2Zz4=";
|
||||
|
||||
updateStatus(cameraName, 'Stream stopped successfully', 'success');
|
||||
} else {
|
||||
const error = await response.text();
|
||||
updateStatus(cameraName, `Failed to stop stream: ${error}`, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error stopping stream:', error);
|
||||
updateStatus(cameraName, `Error stopping stream: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh stream for a camera
|
||||
function refreshStream(cameraName) {
|
||||
const streamImg = document.getElementById(`stream-${cameraName}`);
|
||||
if (streamImg.src.includes('/stream')) {
|
||||
streamImg.src = `${API_BASE}/cameras/${cameraName}/stream?t=${Date.now()}`;
|
||||
updateStatus(cameraName, 'Stream refreshed', 'info');
|
||||
} else {
|
||||
updateStatus(cameraName, 'No active stream to refresh', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Update status message
|
||||
function updateStatus(cameraName, message, type) {
|
||||
const statusDiv = document.getElementById(`status-${cameraName}`);
|
||||
statusDiv.className = `status status-${type}`;
|
||||
statusDiv.textContent = message;
|
||||
}
|
||||
|
||||
// Show error message
|
||||
function showError(message) {
|
||||
alert(`Error: ${message}`);
|
||||
}
|
||||
|
||||
// Initialize when page loads
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
175
API Documentations/docs/API_CHANGES_SUMMARY.md
Normal file
175
API Documentations/docs/API_CHANGES_SUMMARY.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# API Changes Summary: Camera Settings and Filename Handling
|
||||
|
||||
## Overview
|
||||
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
|
||||
627
API Documentations/docs/API_DOCUMENTATION.md
Normal file
627
API Documentations/docs/API_DOCUMENTATION.md
Normal file
@@ -0,0 +1,627 @@
|
||||
# 🚀 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)
|
||||
- [🌐 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": "vibratory_conveyor",
|
||||
"storage_path": "/storage/camera1",
|
||||
"enabled": true,
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.5,
|
||||
"target_fps": 3.0,
|
||||
"auto_start_recording_enabled": true,
|
||||
"sharpness": 120,
|
||||
"contrast": 110,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": true,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": true,
|
||||
"color_temperature_preset": 0,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
```
|
||||
|
||||
### Update 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`
|
||||
|
||||
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).
|
||||
|
||||
## 🌐 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
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
### 🔄 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
|
||||
- [🔧 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
|
||||
- `404`: Resource not found (camera, file, etc.)
|
||||
- `500`: Internal server error
|
||||
- `503`: Service unavailable (camera manager, MQTT, etc.)
|
||||
|
||||
### 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
API Documentations/docs/API_QUICK_REFERENCE.md
Normal file
195
API Documentations/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
|
||||
212
API Documentations/docs/PROJECT_COMPLETE.md
Normal file
212
API Documentations/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
|
||||
65
API Documentations/docs/README.md
Normal file
65
API Documentations/docs/README.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 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
|
||||
|
||||
### 🔧 [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.
|
||||
425
API Documentations/docs/api/CAMERA_CONFIG_API.md
Normal file
425
API Documentations/docs/api/CAMERA_CONFIG_API.md
Normal file
@@ -0,0 +1,425 @@
|
||||
# 🎛️ 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`
|
||||
- **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`
|
||||
- **System**: `machine_topic`, `storage_path`, `enabled`, `bit_depth`
|
||||
|
||||
## 🔌 API Endpoints
|
||||
|
||||
### 1. Get Camera Configuration
|
||||
```http
|
||||
GET /cameras/{camera_name}/config
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"name": "camera1",
|
||||
"machine_topic": "vibratory_conveyor",
|
||||
"storage_path": "/storage/camera1",
|
||||
"enabled": true,
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.5,
|
||||
"target_fps": 0,
|
||||
"sharpness": 120,
|
||||
"contrast": 110,
|
||||
"saturation": 100,
|
||||
"gamma": 100,
|
||||
"noise_filter_enabled": true,
|
||||
"denoise_3d_enabled": false,
|
||||
"auto_white_balance": true,
|
||||
"color_temperature_preset": 0,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"bit_depth": 8,
|
||||
"hdr_enabled": false,
|
||||
"hdr_gain_mode": 0
|
||||
}
|
||||
```
|
||||
|
||||
### 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,
|
||||
"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"]
|
||||
}
|
||||
```
|
||||
|
||||
### 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
|
||||
|
||||
### 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) |
|
||||
|
||||
### 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>
|
||||
|
||||
{/* 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>
|
||||
|
||||
{/* 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!
|
||||
262
API Documentations/docs/features/AUTO_RECORDING_FEATURE_GUIDE.md
Normal file
262
API Documentations/docs/features/AUTO_RECORDING_FEATURE_GUIDE.md
Normal file
@@ -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
API Documentations/docs/guides/CAMERA_RECOVERY_GUIDE.md
Normal file
158
API Documentations/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
API Documentations/docs/guides/MQTT_LOGGING_GUIDE.md
Normal file
187
API Documentations/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
API Documentations/docs/guides/STREAMING_GUIDE.md
Normal file
240
API Documentations/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
API Documentations/docs/legacy/01README.md
Normal file
146
API Documentations/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
API Documentations/docs/legacy/IMPLEMENTATION_SUMMARY.md
Normal file
184
API Documentations/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
API Documentations/docs/legacy/README.md
Normal file
1
API Documentations/docs/legacy/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# USDA-Vision-Cameras
|
||||
249
API Documentations/docs/legacy/README_SYSTEM.md
Normal file
249
API Documentations/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
API Documentations/docs/legacy/TIMEZONE_SETUP_SUMMARY.md
Normal file
190
API Documentations/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
API Documentations/docs/legacy/VIDEO_RECORDER_README.md
Normal file
191
API Documentations/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
|
||||
524
API Documentations/streaming-api.http
Normal file
524
API Documentations/streaming-api.http
Normal file
@@ -0,0 +1,524 @@
|
||||
### USDA Vision Camera Streaming API
|
||||
###
|
||||
### CONFIGURATION:
|
||||
### - Production: http://vision:8000 (requires hostname setup)
|
||||
### - Development: http://localhost:8000
|
||||
### - Custom: Update @baseUrl below to match your setup
|
||||
###
|
||||
### This file contains streaming-specific API endpoints for live camera preview
|
||||
### Use with VS Code REST Client extension or similar tools.
|
||||
|
||||
# Base URL - Update to match your configuration
|
||||
@baseUrl = http://vision:8000
|
||||
# Alternative: @baseUrl = http://localhost:8000
|
||||
|
||||
### =============================================================================
|
||||
### STREAMING ENDPOINTS (NEW FUNCTIONALITY)
|
||||
### =============================================================================
|
||||
|
||||
### Start camera streaming for live preview
|
||||
### This creates a separate camera connection that doesn't interfere with recording
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Started streaming for camera camera1"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Stop camera streaming
|
||||
POST {{baseUrl}}/cameras/camera1/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Stopped streaming for camera camera1"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get live MJPEG stream (open in browser or use as img src)
|
||||
### This endpoint returns a continuous MJPEG stream
|
||||
### Content-Type: multipart/x-mixed-replace; boundary=frame
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
### Usage in HTML:
|
||||
# <img src="http://localhost:8000/cameras/camera1/stream" alt="Live Stream" />
|
||||
|
||||
### Usage in React:
|
||||
# <img src={`${apiBaseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`} />
|
||||
|
||||
###
|
||||
|
||||
### Start streaming for camera2
|
||||
POST {{baseUrl}}/cameras/camera2/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Get live stream for camera2
|
||||
GET {{baseUrl}}/cameras/camera2/stream
|
||||
|
||||
###
|
||||
|
||||
### Stop streaming for camera2
|
||||
POST {{baseUrl}}/cameras/camera2/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### =============================================================================
|
||||
### CONCURRENT OPERATIONS TESTING
|
||||
### =============================================================================
|
||||
|
||||
### Test Scenario: Streaming + Recording Simultaneously
|
||||
### This demonstrates that streaming doesn't block recording
|
||||
|
||||
### Step 1: Start streaming first
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Step 2: Start recording (while streaming continues)
|
||||
POST {{baseUrl}}/cameras/camera1/start-recording
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"filename": "concurrent_test.avi"
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Step 3: Check both are running
|
||||
GET {{baseUrl}}/cameras/camera1
|
||||
|
||||
### Expected Response shows both recording and streaming active:
|
||||
# {
|
||||
# "camera1": {
|
||||
# "name": "camera1",
|
||||
# "status": "connected",
|
||||
# "is_recording": true,
|
||||
# "current_recording_file": "concurrent_test.avi",
|
||||
# "recording_start_time": "2025-01-28T10:30:00.000Z"
|
||||
# }
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Step 4: Stop recording (streaming continues)
|
||||
POST {{baseUrl}}/cameras/camera1/stop-recording
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Step 5: Verify streaming still works
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
###
|
||||
|
||||
### Step 6: Stop streaming
|
||||
POST {{baseUrl}}/cameras/camera1/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### =============================================================================
|
||||
### MULTIPLE CAMERA STREAMING
|
||||
### =============================================================================
|
||||
|
||||
### Start streaming on multiple cameras simultaneously
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
POST {{baseUrl}}/cameras/camera2/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
### Check status of all cameras
|
||||
GET {{baseUrl}}/cameras
|
||||
|
||||
###
|
||||
|
||||
### Access multiple streams (open in separate browser tabs)
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
###
|
||||
|
||||
GET {{baseUrl}}/cameras/camera2/stream
|
||||
|
||||
###
|
||||
|
||||
### Stop all streaming
|
||||
POST {{baseUrl}}/cameras/camera1/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
###
|
||||
|
||||
POST {{baseUrl}}/cameras/camera2/stop-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### =============================================================================
|
||||
### ERROR TESTING
|
||||
### =============================================================================
|
||||
|
||||
### Test with invalid camera name
|
||||
POST {{baseUrl}}/cameras/invalid_camera/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "detail": "Camera streamer not found: invalid_camera"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Test stream endpoint without starting stream first
|
||||
GET {{baseUrl}}/cameras/camera1/stream
|
||||
|
||||
### Expected: May return error or empty stream depending on camera state
|
||||
|
||||
###
|
||||
|
||||
### Test starting stream when camera is in error state
|
||||
POST {{baseUrl}}/cameras/camera1/start-stream
|
||||
Content-Type: application/json
|
||||
|
||||
### If camera has issues, expected response:
|
||||
# {
|
||||
# "success": false,
|
||||
# "message": "Failed to start streaming for camera camera1"
|
||||
# }
|
||||
|
||||
### =============================================================================
|
||||
### INTEGRATION EXAMPLES FOR AI ASSISTANTS
|
||||
### =============================================================================
|
||||
|
||||
### React Component Integration:
|
||||
# const CameraStream = ({ cameraName }) => {
|
||||
# const [isStreaming, setIsStreaming] = useState(false);
|
||||
#
|
||||
# const startStream = async () => {
|
||||
# const response = await fetch(`${baseUrl}/cameras/${cameraName}/start-stream`, {
|
||||
# method: 'POST'
|
||||
# });
|
||||
# if (response.ok) {
|
||||
# setIsStreaming(true);
|
||||
# }
|
||||
# };
|
||||
#
|
||||
# return (
|
||||
# <div>
|
||||
# <button onClick={startStream}>Start Stream</button>
|
||||
# {isStreaming && (
|
||||
# <img src={`${baseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`} />
|
||||
# )}
|
||||
# </div>
|
||||
# );
|
||||
# };
|
||||
|
||||
### JavaScript Fetch Example:
|
||||
# const streamAPI = {
|
||||
# async startStream(cameraName) {
|
||||
# const response = await fetch(`${baseUrl}/cameras/${cameraName}/start-stream`, {
|
||||
# method: 'POST',
|
||||
# headers: { 'Content-Type': 'application/json' }
|
||||
# });
|
||||
# return response.json();
|
||||
# },
|
||||
#
|
||||
# async stopStream(cameraName) {
|
||||
# const response = await fetch(`${baseUrl}/cameras/${cameraName}/stop-stream`, {
|
||||
# method: 'POST',
|
||||
# headers: { 'Content-Type': 'application/json' }
|
||||
# });
|
||||
# return response.json();
|
||||
# },
|
||||
#
|
||||
# getStreamUrl(cameraName) {
|
||||
# return `${baseUrl}/cameras/${cameraName}/stream?t=${Date.now()}`;
|
||||
# }
|
||||
# };
|
||||
|
||||
### Vue.js Integration:
|
||||
# <template>
|
||||
# <div>
|
||||
# <button @click="startStream">Start Stream</button>
|
||||
# <img v-if="isStreaming" :src="streamUrl" />
|
||||
# </div>
|
||||
# </template>
|
||||
#
|
||||
# <script>
|
||||
# export default {
|
||||
# data() {
|
||||
# return {
|
||||
# isStreaming: false,
|
||||
# cameraName: 'camera1'
|
||||
# };
|
||||
# },
|
||||
# computed: {
|
||||
# streamUrl() {
|
||||
# return `${this.baseUrl}/cameras/${this.cameraName}/stream?t=${Date.now()}`;
|
||||
# }
|
||||
# },
|
||||
# methods: {
|
||||
# async startStream() {
|
||||
# const response = await fetch(`${this.baseUrl}/cameras/${this.cameraName}/start-stream`, {
|
||||
# method: 'POST'
|
||||
# });
|
||||
# if (response.ok) {
|
||||
# this.isStreaming = true;
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
# };
|
||||
# </script>
|
||||
|
||||
### =============================================================================
|
||||
### TROUBLESHOOTING
|
||||
### =============================================================================
|
||||
|
||||
### If streams don't start:
|
||||
# 1. Check camera status: GET /cameras
|
||||
# 2. Verify system health: GET /health
|
||||
# 3. Test camera connection: POST /cameras/{name}/test-connection
|
||||
# 4. Check if camera is already recording (shouldn't matter, but good to know)
|
||||
|
||||
### If stream image doesn't load:
|
||||
# 1. Verify stream was started: POST /cameras/{name}/start-stream
|
||||
# 2. Check browser console for CORS errors
|
||||
# 3. Try accessing stream URL directly in browser
|
||||
# 4. Add timestamp to prevent caching: ?t=${Date.now()}
|
||||
|
||||
### If concurrent operations fail:
|
||||
# 1. This should work - streaming and recording use separate connections
|
||||
# 2. Check system logs for resource conflicts
|
||||
# 3. Verify sufficient system resources (CPU/Memory)
|
||||
# 4. Test with one camera first, then multiple
|
||||
|
||||
### Performance Notes:
|
||||
# - Streaming uses ~10 FPS by default (configurable)
|
||||
# - JPEG quality set to 70% (configurable)
|
||||
# - Each stream uses additional CPU/memory
|
||||
# - Multiple concurrent streams may impact performance
|
||||
|
||||
### =============================================================================
|
||||
### CAMERA CONFIGURATION ENDPOINTS (NEW)
|
||||
### =============================================================================
|
||||
|
||||
### Get camera configuration
|
||||
GET {{baseUrl}}/cameras/camera1/config
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "name": "camera1",
|
||||
# "machine_topic": "vibratory_conveyor",
|
||||
# "storage_path": "/storage/camera1",
|
||||
# "enabled": true,
|
||||
# "exposure_ms": 1.0,
|
||||
# "gain": 3.5,
|
||||
# "target_fps": 0,
|
||||
# "sharpness": 120,
|
||||
# "contrast": 110,
|
||||
# "saturation": 100,
|
||||
# "gamma": 100,
|
||||
# "noise_filter_enabled": true,
|
||||
# "denoise_3d_enabled": false,
|
||||
# "auto_white_balance": true,
|
||||
# "color_temperature_preset": 0,
|
||||
# "anti_flicker_enabled": true,
|
||||
# "light_frequency": 1,
|
||||
# "bit_depth": 8,
|
||||
# "hdr_enabled": false,
|
||||
# "hdr_gain_mode": 0
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Update basic camera settings (real-time, no restart required)
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 2.0,
|
||||
"gain": 4.0,
|
||||
"target_fps": 10.0
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update image quality settings
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"sharpness": 150,
|
||||
"contrast": 120,
|
||||
"saturation": 110,
|
||||
"gamma": 90
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update advanced settings
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1,
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 2
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Enable HDR mode
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"hdr_enabled": true,
|
||||
"hdr_gain_mode": 1
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Update noise reduction settings (requires restart)
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"noise_filter_enabled": false,
|
||||
"denoise_3d_enabled": true
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Apply configuration (restart camera with new settings)
|
||||
POST {{baseUrl}}/cameras/camera1/apply-config
|
||||
|
||||
### Expected Response:
|
||||
# {
|
||||
# "success": true,
|
||||
# "message": "Configuration applied to camera camera1"
|
||||
# }
|
||||
|
||||
###
|
||||
|
||||
### Get camera2 configuration
|
||||
GET {{baseUrl}}/cameras/camera2/config
|
||||
|
||||
###
|
||||
|
||||
### Update camera2 for outdoor lighting
|
||||
PUT {{baseUrl}}/cameras/camera2/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 0.5,
|
||||
"gain": 2.0,
|
||||
"sharpness": 130,
|
||||
"contrast": 115,
|
||||
"anti_flicker_enabled": true,
|
||||
"light_frequency": 1
|
||||
}
|
||||
|
||||
### =============================================================================
|
||||
### CONFIGURATION TESTING SCENARIOS
|
||||
### =============================================================================
|
||||
|
||||
### Scenario 1: Low light optimization
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 5.0,
|
||||
"gain": 8.0,
|
||||
"noise_filter_enabled": true,
|
||||
"denoise_3d_enabled": true
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Scenario 2: High speed capture
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 0.2,
|
||||
"gain": 1.0,
|
||||
"target_fps": 30.0,
|
||||
"sharpness": 180
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Scenario 3: Color accuracy for food inspection
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"auto_white_balance": false,
|
||||
"color_temperature_preset": 1,
|
||||
"saturation": 120,
|
||||
"contrast": 105,
|
||||
"gamma": 95
|
||||
}
|
||||
|
||||
###
|
||||
|
||||
### Scenario 4: HDR for high contrast scenes
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"hdr_enabled": true,
|
||||
"hdr_gain_mode": 2,
|
||||
"exposure_ms": 1.0,
|
||||
"gain": 3.0
|
||||
}
|
||||
|
||||
### =============================================================================
|
||||
### ERROR TESTING FOR CONFIGURATION
|
||||
### =============================================================================
|
||||
|
||||
### Test invalid camera name
|
||||
GET {{baseUrl}}/cameras/invalid_camera/config
|
||||
|
||||
###
|
||||
|
||||
### Test invalid exposure range
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"exposure_ms": 2000.0
|
||||
}
|
||||
|
||||
### Expected: HTTP 422 validation error
|
||||
|
||||
###
|
||||
|
||||
### Test invalid gain range
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"gain": 50.0
|
||||
}
|
||||
|
||||
### Expected: HTTP 422 validation error
|
||||
|
||||
###
|
||||
|
||||
### Test empty configuration update
|
||||
PUT {{baseUrl}}/cameras/camera1/config
|
||||
Content-Type: application/json
|
||||
|
||||
{}
|
||||
|
||||
### Expected: HTTP 400 "No configuration updates provided"
|
||||
80
API Documentations/test_frame_conversion.py
Normal file
80
API Documentations/test_frame_conversion.py
Normal file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to verify the frame conversion fix works correctly.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import numpy as np
|
||||
|
||||
# Add the current directory to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# Add camera SDK to path
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), "camera_sdk"))
|
||||
|
||||
try:
|
||||
import mvsdk
|
||||
print("✅ mvsdk imported successfully")
|
||||
except ImportError as e:
|
||||
print(f"❌ Failed to import mvsdk: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def test_frame_conversion():
|
||||
"""Test the frame conversion logic"""
|
||||
print("🧪 Testing frame conversion logic...")
|
||||
|
||||
# Simulate frame data
|
||||
width, height = 640, 480
|
||||
frame_size = width * height * 3 # RGB
|
||||
|
||||
# Create mock frame data
|
||||
mock_frame_data = np.random.randint(0, 255, frame_size, dtype=np.uint8)
|
||||
|
||||
# Create a mock frame buffer (simulate memory address)
|
||||
frame_buffer = mock_frame_data.ctypes.data
|
||||
|
||||
# Create mock FrameHead
|
||||
class MockFrameHead:
|
||||
def __init__(self):
|
||||
self.iWidth = width
|
||||
self.iHeight = height
|
||||
self.uBytes = frame_size
|
||||
|
||||
frame_head = MockFrameHead()
|
||||
|
||||
try:
|
||||
# Test the conversion logic (similar to what's in streamer.py)
|
||||
frame_data_buffer = (mvsdk.c_ubyte * frame_head.uBytes).from_address(frame_buffer)
|
||||
frame_data = np.frombuffer(frame_data_buffer, dtype=np.uint8)
|
||||
frame = frame_data.reshape((frame_head.iHeight, frame_head.iWidth, 3))
|
||||
|
||||
print(f"✅ Frame conversion successful!")
|
||||
print(f" Frame shape: {frame.shape}")
|
||||
print(f" Frame dtype: {frame.dtype}")
|
||||
print(f" Frame size: {frame.size} bytes")
|
||||
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Frame conversion failed: {e}")
|
||||
return False
|
||||
|
||||
def main():
|
||||
print("🔧 Frame Conversion Test")
|
||||
print("=" * 40)
|
||||
|
||||
success = test_frame_conversion()
|
||||
|
||||
if success:
|
||||
print("\n✅ Frame conversion fix is working correctly!")
|
||||
print("📋 The streaming issue should be resolved after system restart.")
|
||||
else:
|
||||
print("\n❌ Frame conversion fix needs more work.")
|
||||
|
||||
print("\n💡 To apply the fix:")
|
||||
print("1. Restart the USDA vision system")
|
||||
print("2. Test streaming again")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
199
API Documentations/test_streaming.py
Normal file
199
API Documentations/test_streaming.py
Normal file
@@ -0,0 +1,199 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for camera streaming functionality.
|
||||
|
||||
This script tests the new streaming capabilities without interfering with recording.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import requests
|
||||
import threading
|
||||
from datetime import datetime
|
||||
|
||||
# Add the current directory to Python path
|
||||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
def test_api_endpoints():
|
||||
"""Test the streaming API endpoints"""
|
||||
base_url = "http://localhost:8000"
|
||||
|
||||
print("🧪 Testing Camera Streaming API Endpoints")
|
||||
print("=" * 50)
|
||||
|
||||
# Test system status
|
||||
try:
|
||||
response = requests.get(f"{base_url}/system/status", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("✅ System status endpoint working")
|
||||
data = response.json()
|
||||
print(f" System: {data.get('status', 'Unknown')}")
|
||||
print(f" Camera Manager: {'Running' if data.get('camera_manager_running') else 'Stopped'}")
|
||||
else:
|
||||
print(f"❌ System status endpoint failed: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"❌ System status endpoint error: {e}")
|
||||
|
||||
# Test camera list
|
||||
try:
|
||||
response = requests.get(f"{base_url}/cameras", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("✅ Camera list endpoint working")
|
||||
cameras = response.json()
|
||||
print(f" Found {len(cameras)} cameras: {list(cameras.keys())}")
|
||||
|
||||
# Test streaming for each camera
|
||||
for camera_name in cameras.keys():
|
||||
test_camera_streaming(base_url, camera_name)
|
||||
|
||||
else:
|
||||
print(f"❌ Camera list endpoint failed: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"❌ Camera list endpoint error: {e}")
|
||||
|
||||
def test_camera_streaming(base_url, camera_name):
|
||||
"""Test streaming for a specific camera"""
|
||||
print(f"\n🎥 Testing streaming for {camera_name}")
|
||||
print("-" * 30)
|
||||
|
||||
# Test start streaming
|
||||
try:
|
||||
response = requests.post(f"{base_url}/cameras/{camera_name}/start-stream", timeout=10)
|
||||
if response.status_code == 200:
|
||||
print(f"✅ Start stream endpoint working for {camera_name}")
|
||||
data = response.json()
|
||||
print(f" Response: {data.get('message', 'No message')}")
|
||||
else:
|
||||
print(f"❌ Start stream failed for {camera_name}: {response.status_code}")
|
||||
print(f" Error: {response.text}")
|
||||
return
|
||||
except Exception as e:
|
||||
print(f"❌ Start stream error for {camera_name}: {e}")
|
||||
return
|
||||
|
||||
# Wait a moment for stream to initialize
|
||||
time.sleep(2)
|
||||
|
||||
# Test stream endpoint (just check if it responds)
|
||||
try:
|
||||
response = requests.get(f"{base_url}/cameras/{camera_name}/stream", timeout=5, stream=True)
|
||||
if response.status_code == 200:
|
||||
print(f"✅ Stream endpoint responding for {camera_name}")
|
||||
print(f" Content-Type: {response.headers.get('content-type', 'Unknown')}")
|
||||
|
||||
# Read a small amount of data to verify it's working
|
||||
chunk_count = 0
|
||||
for chunk in response.iter_content(chunk_size=1024):
|
||||
chunk_count += 1
|
||||
if chunk_count >= 3: # Read a few chunks then stop
|
||||
break
|
||||
|
||||
print(f" Received {chunk_count} data chunks")
|
||||
else:
|
||||
print(f"❌ Stream endpoint failed for {camera_name}: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"❌ Stream endpoint error for {camera_name}: {e}")
|
||||
|
||||
# Test stop streaming
|
||||
try:
|
||||
response = requests.post(f"{base_url}/cameras/{camera_name}/stop-stream", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print(f"✅ Stop stream endpoint working for {camera_name}")
|
||||
data = response.json()
|
||||
print(f" Response: {data.get('message', 'No message')}")
|
||||
else:
|
||||
print(f"❌ Stop stream failed for {camera_name}: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"❌ Stop stream error for {camera_name}: {e}")
|
||||
|
||||
def test_concurrent_recording_and_streaming():
|
||||
"""Test that streaming doesn't interfere with recording"""
|
||||
base_url = "http://localhost:8000"
|
||||
|
||||
print("\n🔄 Testing Concurrent Recording and Streaming")
|
||||
print("=" * 50)
|
||||
|
||||
try:
|
||||
# Get available cameras
|
||||
response = requests.get(f"{base_url}/cameras", timeout=5)
|
||||
if response.status_code != 200:
|
||||
print("❌ Cannot get camera list for concurrent test")
|
||||
return
|
||||
|
||||
cameras = response.json()
|
||||
if not cameras:
|
||||
print("❌ No cameras available for concurrent test")
|
||||
return
|
||||
|
||||
camera_name = list(cameras.keys())[0] # Use first camera
|
||||
print(f"Using camera: {camera_name}")
|
||||
|
||||
# Start streaming
|
||||
print("1. Starting streaming...")
|
||||
response = requests.post(f"{base_url}/cameras/{camera_name}/start-stream", timeout=10)
|
||||
if response.status_code != 200:
|
||||
print(f"❌ Failed to start streaming: {response.text}")
|
||||
return
|
||||
|
||||
time.sleep(2)
|
||||
|
||||
# Start recording
|
||||
print("2. Starting recording...")
|
||||
response = requests.post(f"{base_url}/cameras/{camera_name}/start-recording",
|
||||
json={"filename": "test_concurrent_recording.avi"}, timeout=10)
|
||||
if response.status_code == 200:
|
||||
print("✅ Recording started successfully while streaming")
|
||||
else:
|
||||
print(f"❌ Failed to start recording while streaming: {response.text}")
|
||||
|
||||
# Let both run for a few seconds
|
||||
print("3. Running both streaming and recording for 5 seconds...")
|
||||
time.sleep(5)
|
||||
|
||||
# Stop recording
|
||||
print("4. Stopping recording...")
|
||||
response = requests.post(f"{base_url}/cameras/{camera_name}/stop-recording", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("✅ Recording stopped successfully")
|
||||
else:
|
||||
print(f"❌ Failed to stop recording: {response.text}")
|
||||
|
||||
# Stop streaming
|
||||
print("5. Stopping streaming...")
|
||||
response = requests.post(f"{base_url}/cameras/{camera_name}/stop-stream", timeout=5)
|
||||
if response.status_code == 200:
|
||||
print("✅ Streaming stopped successfully")
|
||||
else:
|
||||
print(f"❌ Failed to stop streaming: {response.text}")
|
||||
|
||||
print("✅ Concurrent test completed successfully!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Concurrent test error: {e}")
|
||||
|
||||
def main():
|
||||
"""Main test function"""
|
||||
print("🚀 USDA Vision Camera Streaming Test")
|
||||
print("=" * 50)
|
||||
print(f"Test started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
print()
|
||||
|
||||
# Wait for system to be ready
|
||||
print("⏳ Waiting for system to be ready...")
|
||||
time.sleep(3)
|
||||
|
||||
# Run tests
|
||||
test_api_endpoints()
|
||||
test_concurrent_recording_and_streaming()
|
||||
|
||||
print("\n" + "=" * 50)
|
||||
print("🏁 Test completed!")
|
||||
print("\n📋 Next Steps:")
|
||||
print("1. Open camera_preview.html in your browser")
|
||||
print("2. Click 'Start Stream' for any camera")
|
||||
print("3. Verify live preview works without blocking recording")
|
||||
print("4. Test concurrent recording and streaming")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user