updates
This commit is contained in:
267
README.md
267
README.md
@@ -213,8 +213,14 @@ system.stop()
|
||||
# Start the API server
|
||||
wifi-densepose start
|
||||
|
||||
# Or using Python
|
||||
python -m wifi_densepose.main
|
||||
# Start with custom configuration
|
||||
wifi-densepose -c /path/to/config.yaml start
|
||||
|
||||
# Start with verbose logging
|
||||
wifi-densepose -v start
|
||||
|
||||
# Check server status
|
||||
wifi-densepose status
|
||||
```
|
||||
|
||||
The API will be available at `http://localhost:8000`
|
||||
@@ -255,180 +261,229 @@ The CLI is automatically installed with the package:
|
||||
pip install wifi-densepose
|
||||
|
||||
# Verify CLI installation
|
||||
wifi-densepose --version
|
||||
wifi-densepose --help
|
||||
wifi-densepose version
|
||||
```
|
||||
|
||||
### Basic Commands
|
||||
|
||||
#### Start/Stop System
|
||||
The WiFi-DensePose CLI provides the following commands:
|
||||
|
||||
```bash
|
||||
# Start the WiFi DensePose system
|
||||
wifi-densepose [OPTIONS] COMMAND [ARGS]...
|
||||
|
||||
Options:
|
||||
-c, --config PATH Path to configuration file
|
||||
-v, --verbose Enable verbose logging
|
||||
--debug Enable debug mode
|
||||
--help Show this message and exit.
|
||||
|
||||
Commands:
|
||||
config Configuration management commands.
|
||||
db Database management commands.
|
||||
start Start the WiFi-DensePose API server.
|
||||
status Show the status of the WiFi-DensePose API server.
|
||||
stop Stop the WiFi-DensePose API server.
|
||||
tasks Background task management commands.
|
||||
version Show version information.
|
||||
```
|
||||
|
||||
#### Server Management
|
||||
```bash
|
||||
# Start the WiFi-DensePose API server
|
||||
wifi-densepose start
|
||||
|
||||
# Start with custom configuration
|
||||
wifi-densepose start --config /path/to/config.yaml
|
||||
wifi-densepose -c /path/to/config.yaml start
|
||||
|
||||
# Start in development mode
|
||||
wifi-densepose start --dev
|
||||
# Start with verbose logging
|
||||
wifi-densepose -v start
|
||||
|
||||
# Stop the system
|
||||
wifi-densepose stop
|
||||
# Start with debug mode
|
||||
wifi-densepose --debug start
|
||||
|
||||
# Restart the system
|
||||
wifi-densepose restart
|
||||
```
|
||||
|
||||
#### System Status
|
||||
```bash
|
||||
# Check system status
|
||||
# Check server status
|
||||
wifi-densepose status
|
||||
|
||||
# Get detailed health information
|
||||
wifi-densepose health
|
||||
# Stop the server
|
||||
wifi-densepose stop
|
||||
|
||||
# Show system information
|
||||
wifi-densepose info
|
||||
```
|
||||
|
||||
#### Pose Data Operations
|
||||
```bash
|
||||
# Get latest pose data
|
||||
wifi-densepose pose latest
|
||||
|
||||
# Get pose history
|
||||
wifi-densepose pose history --hours 24
|
||||
|
||||
# Stream pose data to console
|
||||
wifi-densepose pose stream
|
||||
|
||||
# Export pose data
|
||||
wifi-densepose pose export --format json --output poses.json
|
||||
# Show version information
|
||||
wifi-densepose version
|
||||
```
|
||||
|
||||
### Configuration Commands
|
||||
|
||||
#### Environment Setup
|
||||
#### Configuration Management
|
||||
```bash
|
||||
# Initialize configuration
|
||||
wifi-densepose init
|
||||
|
||||
# Create configuration from template
|
||||
wifi-densepose config create --template healthcare
|
||||
|
||||
# Validate configuration
|
||||
wifi-densepose config validate
|
||||
# Configuration management commands
|
||||
wifi-densepose config [SUBCOMMAND]
|
||||
|
||||
# Examples:
|
||||
# Show current configuration
|
||||
wifi-densepose config show
|
||||
|
||||
# Validate configuration file
|
||||
wifi-densepose config validate
|
||||
|
||||
# Create default configuration
|
||||
wifi-densepose config init
|
||||
|
||||
# Edit configuration
|
||||
wifi-densepose config edit
|
||||
```
|
||||
|
||||
#### Hardware Configuration
|
||||
#### Database Management
|
||||
```bash
|
||||
# List available WiFi interfaces
|
||||
wifi-densepose hardware list-interfaces
|
||||
# Database management commands
|
||||
wifi-densepose db [SUBCOMMAND]
|
||||
|
||||
# Test hardware connectivity
|
||||
wifi-densepose hardware test
|
||||
# Examples:
|
||||
# Initialize database
|
||||
wifi-densepose db init
|
||||
|
||||
# Calibrate environment
|
||||
wifi-densepose calibrate --duration 10 --environment room_001
|
||||
# Run database migrations
|
||||
wifi-densepose db migrate
|
||||
|
||||
# Show hardware status
|
||||
wifi-densepose hardware status
|
||||
# Check database status
|
||||
wifi-densepose db status
|
||||
|
||||
# Backup database
|
||||
wifi-densepose db backup
|
||||
|
||||
# Restore database
|
||||
wifi-densepose db restore
|
||||
```
|
||||
|
||||
### Monitoring Commands
|
||||
|
||||
#### Real-time Monitoring
|
||||
#### Background Tasks
|
||||
```bash
|
||||
# Monitor system performance
|
||||
wifi-densepose monitor
|
||||
# Background task management commands
|
||||
wifi-densepose tasks [SUBCOMMAND]
|
||||
|
||||
# Monitor pose detection in real-time
|
||||
wifi-densepose monitor poses
|
||||
# Examples:
|
||||
# List running tasks
|
||||
wifi-densepose tasks list
|
||||
|
||||
# Monitor system logs
|
||||
wifi-densepose logs --follow
|
||||
# Start background tasks
|
||||
wifi-densepose tasks start
|
||||
|
||||
# Monitor specific component
|
||||
wifi-densepose monitor --component csi_processor
|
||||
# Stop background tasks
|
||||
wifi-densepose tasks stop
|
||||
|
||||
# Check task status
|
||||
wifi-densepose tasks status
|
||||
```
|
||||
|
||||
#### Analytics and Reports
|
||||
### Command Examples
|
||||
|
||||
#### Complete CLI Reference
|
||||
```bash
|
||||
# Generate analytics report
|
||||
wifi-densepose analytics report --period 24h
|
||||
# Show help for main command
|
||||
wifi-densepose --help
|
||||
|
||||
# Show fall detection events
|
||||
wifi-densepose analytics falls --since yesterday
|
||||
# Show help for specific command
|
||||
wifi-densepose start --help
|
||||
wifi-densepose config --help
|
||||
wifi-densepose db --help
|
||||
|
||||
# Export system metrics
|
||||
wifi-densepose metrics export --format csv
|
||||
# Use global options with commands
|
||||
wifi-densepose -v status # Verbose status check
|
||||
wifi-densepose --debug start # Start with debug logging
|
||||
wifi-densepose -c custom.yaml start # Start with custom config
|
||||
```
|
||||
|
||||
#### Common Usage Patterns
|
||||
```bash
|
||||
# Basic server lifecycle
|
||||
wifi-densepose start # Start the server
|
||||
wifi-densepose status # Check if running
|
||||
wifi-densepose stop # Stop the server
|
||||
|
||||
# Configuration management
|
||||
wifi-densepose config show # View current config
|
||||
wifi-densepose config validate # Check config validity
|
||||
|
||||
# Database operations
|
||||
wifi-densepose db init # Initialize database
|
||||
wifi-densepose db migrate # Run migrations
|
||||
wifi-densepose db status # Check database health
|
||||
|
||||
# Task management
|
||||
wifi-densepose tasks list # List background tasks
|
||||
wifi-densepose tasks status # Check task status
|
||||
|
||||
# Version and help
|
||||
wifi-densepose version # Show version info
|
||||
wifi-densepose --help # Show help message
|
||||
```
|
||||
|
||||
### CLI Examples
|
||||
|
||||
#### Complete Setup Workflow
|
||||
```bash
|
||||
# 1. Initialize new environment
|
||||
wifi-densepose init --environment healthcare
|
||||
# 1. Check version and help
|
||||
wifi-densepose version
|
||||
wifi-densepose --help
|
||||
|
||||
# 2. Configure hardware
|
||||
wifi-densepose hardware setup --interface wlan0
|
||||
# 2. Initialize configuration
|
||||
wifi-densepose config init
|
||||
|
||||
# 3. Calibrate environment
|
||||
wifi-densepose calibrate --duration 15
|
||||
# 3. Initialize database
|
||||
wifi-densepose db init
|
||||
|
||||
# 4. Start system
|
||||
# 4. Start the server
|
||||
wifi-densepose start
|
||||
|
||||
# 5. Monitor in real-time
|
||||
wifi-densepose monitor poses
|
||||
# 5. Check status
|
||||
wifi-densepose status
|
||||
```
|
||||
|
||||
#### Development Workflow
|
||||
```bash
|
||||
# Start in development mode with mock data
|
||||
wifi-densepose start --dev --mock-hardware
|
||||
# Start with debug logging
|
||||
wifi-densepose --debug start
|
||||
|
||||
# Run tests
|
||||
wifi-densepose test
|
||||
# Use custom configuration
|
||||
wifi-densepose -c dev-config.yaml start
|
||||
|
||||
# Check code quality
|
||||
wifi-densepose lint
|
||||
# Check database status
|
||||
wifi-densepose db status
|
||||
|
||||
# Generate documentation
|
||||
wifi-densepose docs generate
|
||||
# Manage background tasks
|
||||
wifi-densepose tasks start
|
||||
wifi-densepose tasks list
|
||||
```
|
||||
|
||||
#### Production Deployment
|
||||
#### Production Workflow
|
||||
```bash
|
||||
# Deploy to production
|
||||
wifi-densepose deploy --environment production
|
||||
# Start with production config
|
||||
wifi-densepose -c production.yaml start
|
||||
|
||||
# Check deployment status
|
||||
wifi-densepose deploy status
|
||||
# Check system status
|
||||
wifi-densepose status
|
||||
|
||||
# Scale system
|
||||
wifi-densepose scale --replicas 3
|
||||
# Manage database
|
||||
wifi-densepose db migrate
|
||||
wifi-densepose db backup
|
||||
|
||||
# Update system
|
||||
wifi-densepose update --version 1.2.0
|
||||
# Monitor tasks
|
||||
wifi-densepose tasks status
|
||||
```
|
||||
|
||||
#### Troubleshooting
|
||||
```bash
|
||||
# Run system diagnostics
|
||||
wifi-densepose diagnose
|
||||
# Enable verbose logging
|
||||
wifi-densepose -v status
|
||||
|
||||
# Check hardware connectivity
|
||||
wifi-densepose hardware test --verbose
|
||||
# Check configuration
|
||||
wifi-densepose config validate
|
||||
|
||||
# Validate configuration
|
||||
wifi-densepose config validate --strict
|
||||
# Check database health
|
||||
wifi-densepose db status
|
||||
|
||||
# Reset to defaults
|
||||
wifi-densepose reset --confirm
|
||||
# Restart services
|
||||
wifi-densepose stop
|
||||
wifi-densepose start
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
206
plans/overview.md
Normal file
206
plans/overview.md
Normal file
@@ -0,0 +1,206 @@
|
||||
# WiFi-DensePose System Implementation Overview
|
||||
|
||||
## Project Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ WiFi-DensePose System │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Frontend Layer (React/TypeScript) │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Dashboard │ │ Real-time │ │ Config │ │
|
||||
│ │ UI │ │ Monitoring │ │ Management │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ API & Middleware Layer (FastAPI/Python) │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ REST API │ │ WebSocket │ │ Auth & │ │
|
||||
│ │ Endpoints │ │ Real-time │ │ Validation │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Neural Network Layer (PyTorch/TensorFlow) │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ DensePose │ │ CSI Signal │ │ Pose │ │
|
||||
│ │ Model │ │ Processing │ │ Estimation │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ CSI Processing Layer (Python/C++) │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Data │ │ Signal │ │ Feature │ │
|
||||
│ │ Collection │ │ Processing │ │ Extraction │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Infrastructure Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ WiFi Router │ │ Database │ │ Message │ │
|
||||
│ │ Hardware │ │ (PostgreSQL)│ │ Queue │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Backend Technologies
|
||||
- **Framework**: FastAPI (Python 3.9+)
|
||||
- **Neural Networks**: PyTorch 2.0+, TensorFlow 2.x
|
||||
- **Database**: PostgreSQL 14+, Redis (caching)
|
||||
- **Message Queue**: RabbitMQ/Celery
|
||||
- **CSI Processing**: NumPy, SciPy, custom C++ modules
|
||||
- **Testing**: pytest, pytest-asyncio, pytest-mock
|
||||
|
||||
### Frontend Technologies
|
||||
- **Framework**: React 18+ with TypeScript
|
||||
- **State Management**: Redux Toolkit
|
||||
- **UI Components**: Material-UI v5
|
||||
- **Real-time**: Socket.IO client
|
||||
- **Testing**: Jest, React Testing Library, Cypress
|
||||
|
||||
### Infrastructure
|
||||
- **Containerization**: Docker, Docker Compose
|
||||
- **Orchestration**: Kubernetes
|
||||
- **CI/CD**: GitHub Actions
|
||||
- **Monitoring**: Prometheus, Grafana
|
||||
- **Logging**: ELK Stack (Elasticsearch, Logstash, Kibana)
|
||||
|
||||
## Phase Dependencies Flowchart
|
||||
|
||||
```
|
||||
Phase 1: Foundation
|
||||
│
|
||||
├─── Phase 2: CSI Processing ──┐
|
||||
│ │
|
||||
├─── Phase 3: Neural Networks ─┤
|
||||
│ │
|
||||
└─── Phase 4: API Middleware ──┼─── Phase 6: Integration
|
||||
│ │
|
||||
Phase 5: UI Frontend ─────┘ │
|
||||
│
|
||||
Phase 7: Deployment
|
||||
```
|
||||
|
||||
## Implementation Timeline
|
||||
|
||||
| Phase | Duration | Start Date | End Date | Dependencies |
|
||||
|-------|----------|------------|----------|--------------|
|
||||
| Phase 1: Foundation | 2 weeks | Week 1 | Week 2 | None |
|
||||
| Phase 2: CSI Processing | 3 weeks | Week 2 | Week 4 | Phase 1 |
|
||||
| Phase 3: Neural Networks | 4 weeks | Week 3 | Week 6 | Phase 1, 2 |
|
||||
| Phase 4: API Middleware | 3 weeks | Week 4 | Week 6 | Phase 1, 2 |
|
||||
| Phase 5: UI Frontend | 3 weeks | Week 5 | Week 7 | Phase 4 |
|
||||
| Phase 6: Integration | 2 weeks | Week 7 | Week 8 | All previous |
|
||||
| Phase 7: Deployment | 1 week | Week 9 | Week 9 | Phase 6 |
|
||||
|
||||
**Total Project Duration**: 9 weeks
|
||||
|
||||
## Risk Assessment and Mitigation Strategies
|
||||
|
||||
### High-Risk Areas
|
||||
|
||||
#### 1. CSI Data Quality and Consistency
|
||||
- **Risk**: Inconsistent or noisy CSI data affecting model accuracy
|
||||
- **Mitigation**:
|
||||
- Implement robust data validation and filtering
|
||||
- Create comprehensive test datasets
|
||||
- Develop fallback mechanisms for poor signal conditions
|
||||
|
||||
#### 2. Neural Network Performance
|
||||
- **Risk**: Model accuracy below acceptable thresholds
|
||||
- **Mitigation**:
|
||||
- Implement multiple model architectures for comparison
|
||||
- Use transfer learning from existing DensePose models
|
||||
- Continuous model validation and retraining pipelines
|
||||
|
||||
#### 3. Real-time Processing Requirements
|
||||
- **Risk**: System unable to meet real-time processing demands
|
||||
- **Mitigation**:
|
||||
- Implement efficient data pipelines with streaming
|
||||
- Use GPU acceleration where possible
|
||||
- Design scalable microservices architecture
|
||||
|
||||
#### 4. Hardware Integration Complexity
|
||||
- **Risk**: Difficulties integrating with various WiFi router models
|
||||
- **Mitigation**:
|
||||
- Create abstraction layer for router interfaces
|
||||
- Extensive testing with multiple router models
|
||||
- Fallback to software-based CSI extraction
|
||||
|
||||
### Medium-Risk Areas
|
||||
|
||||
#### 5. API Performance and Scalability
|
||||
- **Risk**: API bottlenecks under high load
|
||||
- **Mitigation**:
|
||||
- Implement caching strategies
|
||||
- Use async/await patterns throughout
|
||||
- Load testing and performance optimization
|
||||
|
||||
#### 6. Frontend Complexity
|
||||
- **Risk**: Complex real-time UI updates causing performance issues
|
||||
- **Mitigation**:
|
||||
- Implement efficient state management
|
||||
- Use React.memo and useMemo for optimization
|
||||
- Progressive loading and lazy components
|
||||
|
||||
### Low-Risk Areas
|
||||
|
||||
#### 7. Database Performance
|
||||
- **Risk**: Database queries becoming slow with large datasets
|
||||
- **Mitigation**:
|
||||
- Proper indexing strategy
|
||||
- Query optimization
|
||||
- Database connection pooling
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Technical Metrics
|
||||
- **Model Accuracy**: >85% pose estimation accuracy
|
||||
- **Latency**: <100ms end-to-end processing time
|
||||
- **Throughput**: Handle 100+ concurrent users
|
||||
- **Uptime**: 99.9% system availability
|
||||
- **Test Coverage**: >95% code coverage
|
||||
|
||||
### Business Metrics
|
||||
- **User Adoption**: Successful deployment in test environments
|
||||
- **Performance**: Real-time pose tracking with minimal lag
|
||||
- **Scalability**: System handles expected load without degradation
|
||||
- **Maintainability**: Clean, documented, testable codebase
|
||||
|
||||
## Quality Assurance Strategy
|
||||
|
||||
### Testing Approach (London School TDD)
|
||||
- **Unit Tests**: Mock all external dependencies, focus on behavior
|
||||
- **Integration Tests**: Test component interactions with test doubles
|
||||
- **End-to-End Tests**: Full system testing with real data
|
||||
- **Performance Tests**: Load and stress testing
|
||||
- **Security Tests**: Vulnerability scanning and penetration testing
|
||||
|
||||
### Code Quality Standards
|
||||
- **Code Coverage**: Minimum 95% for all modules
|
||||
- **Documentation**: Comprehensive API documentation and code comments
|
||||
- **Code Review**: All code changes require peer review
|
||||
- **Static Analysis**: Automated linting and security scanning
|
||||
- **Continuous Integration**: Automated testing on all commits
|
||||
|
||||
## Deployment Strategy
|
||||
|
||||
### Environment Progression
|
||||
1. **Development**: Local development with Docker Compose
|
||||
2. **Testing**: Automated testing environment with CI/CD
|
||||
3. **Staging**: Production-like environment for final validation
|
||||
4. **Production**: Kubernetes-based production deployment
|
||||
|
||||
### Monitoring and Observability
|
||||
- **Application Metrics**: Custom metrics for pose estimation accuracy
|
||||
- **Infrastructure Metrics**: CPU, memory, network, storage
|
||||
- **Logging**: Structured logging with correlation IDs
|
||||
- **Alerting**: Proactive alerts for system issues
|
||||
- **Tracing**: Distributed tracing for performance analysis
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Phase 1**: Begin with foundation setup and core infrastructure
|
||||
2. **Team Alignment**: Ensure all team members understand the architecture
|
||||
3. **Environment Setup**: Prepare development and testing environments
|
||||
4. **Baseline Metrics**: Establish performance and quality baselines
|
||||
5. **Risk Monitoring**: Regular assessment of identified risks
|
||||
|
||||
This overview provides the strategic framework for the WiFi-DensePose system implementation. Each phase plan will detail specific technical requirements, implementation steps, and success criteria.
|
||||
@@ -42,10 +42,27 @@ class Settings(BaseSettings):
|
||||
database_pool_size: int = Field(default=10, description="Database connection pool size")
|
||||
database_max_overflow: int = Field(default=20, description="Database max overflow connections")
|
||||
|
||||
# Database connection pool settings (alternative naming for compatibility)
|
||||
db_pool_size: int = Field(default=10, description="Database connection pool size")
|
||||
db_max_overflow: int = Field(default=20, description="Database max overflow connections")
|
||||
db_pool_timeout: int = Field(default=30, description="Database pool timeout in seconds")
|
||||
db_pool_recycle: int = Field(default=3600, description="Database pool recycle time in seconds")
|
||||
|
||||
# Database connection settings
|
||||
db_host: Optional[str] = Field(default=None, description="Database host")
|
||||
db_port: int = Field(default=5432, description="Database port")
|
||||
db_name: Optional[str] = Field(default=None, description="Database name")
|
||||
db_user: Optional[str] = Field(default=None, description="Database user")
|
||||
db_password: Optional[str] = Field(default=None, description="Database password")
|
||||
db_echo: bool = Field(default=False, description="Enable database query logging")
|
||||
|
||||
# Redis settings (for caching and rate limiting)
|
||||
redis_url: Optional[str] = Field(default=None, description="Redis connection URL")
|
||||
redis_password: Optional[str] = Field(default=None, description="Redis password")
|
||||
redis_db: int = Field(default=0, description="Redis database number")
|
||||
redis_enabled: bool = Field(default=True, description="Enable Redis")
|
||||
redis_host: str = Field(default="localhost", description="Redis host")
|
||||
redis_port: int = Field(default=6379, description="Redis port")
|
||||
|
||||
# Hardware settings
|
||||
wifi_interface: str = Field(default="wlan0", description="WiFi interface name")
|
||||
@@ -78,6 +95,9 @@ class Settings(BaseSettings):
|
||||
metrics_enabled: bool = Field(default=True, description="Enable metrics collection")
|
||||
health_check_interval: int = Field(default=30, description="Health check interval in seconds")
|
||||
performance_monitoring: bool = Field(default=True, description="Enable performance monitoring")
|
||||
monitoring_interval_seconds: int = Field(default=60, description="Monitoring task interval in seconds")
|
||||
cleanup_interval_seconds: int = Field(default=3600, description="Cleanup task interval in seconds")
|
||||
backup_interval_seconds: int = Field(default=86400, description="Backup task interval in seconds")
|
||||
|
||||
# Storage settings
|
||||
data_storage_path: str = Field(default="./data", description="Data storage directory")
|
||||
@@ -160,6 +180,38 @@ class Settings(BaseSettings):
|
||||
if v < 1:
|
||||
raise ValueError("Workers must be at least 1")
|
||||
return v
|
||||
|
||||
@field_validator("db_port")
|
||||
@classmethod
|
||||
def validate_db_port(cls, v):
|
||||
"""Validate database port."""
|
||||
if not 1 <= v <= 65535:
|
||||
raise ValueError("Database port must be between 1 and 65535")
|
||||
return v
|
||||
|
||||
@field_validator("redis_port")
|
||||
@classmethod
|
||||
def validate_redis_port(cls, v):
|
||||
"""Validate Redis port."""
|
||||
if not 1 <= v <= 65535:
|
||||
raise ValueError("Redis port must be between 1 and 65535")
|
||||
return v
|
||||
|
||||
@field_validator("db_pool_size")
|
||||
@classmethod
|
||||
def validate_db_pool_size(cls, v):
|
||||
"""Validate database pool size."""
|
||||
if v < 1:
|
||||
raise ValueError("Database pool size must be at least 1")
|
||||
return v
|
||||
|
||||
@field_validator("monitoring_interval_seconds", "cleanup_interval_seconds", "backup_interval_seconds")
|
||||
@classmethod
|
||||
def validate_interval_seconds(cls, v):
|
||||
"""Validate interval settings."""
|
||||
if v < 0:
|
||||
raise ValueError("Interval seconds must be non-negative")
|
||||
return v
|
||||
@property
|
||||
def is_development(self) -> bool:
|
||||
"""Check if running in development environment."""
|
||||
@@ -180,6 +232,11 @@ class Settings(BaseSettings):
|
||||
if self.database_url:
|
||||
return self.database_url
|
||||
|
||||
# Build URL from individual components if available
|
||||
if self.db_host and self.db_name and self.db_user:
|
||||
password_part = f":{self.db_password}" if self.db_password else ""
|
||||
return f"postgresql://{self.db_user}{password_part}@{self.db_host}:{self.db_port}/{self.db_name}"
|
||||
|
||||
# Default SQLite database for development
|
||||
if self.is_development:
|
||||
return f"sqlite:///{self.data_storage_path}/wifi_densepose.db"
|
||||
@@ -188,14 +245,15 @@ class Settings(BaseSettings):
|
||||
|
||||
def get_redis_url(self) -> Optional[str]:
|
||||
"""Get Redis URL with fallback."""
|
||||
if not self.redis_enabled:
|
||||
return None
|
||||
|
||||
if self.redis_url:
|
||||
return self.redis_url
|
||||
|
||||
# Default Redis for development
|
||||
if self.is_development:
|
||||
return "redis://localhost:6379/0"
|
||||
|
||||
return None
|
||||
# Build URL from individual components
|
||||
password_part = f":{self.redis_password}@" if self.redis_password else ""
|
||||
return f"redis://{password_part}{self.redis_host}:{self.redis_port}/{self.redis_db}"
|
||||
|
||||
def get_cors_config(self) -> Dict[str, Any]:
|
||||
"""Get CORS configuration."""
|
||||
@@ -318,8 +376,8 @@ def validate_settings(settings: Settings) -> List[str]:
|
||||
if not settings.secret_key or settings.secret_key == "change-me":
|
||||
issues.append("Secret key must be set for production")
|
||||
|
||||
if not settings.database_url:
|
||||
issues.append("Database URL must be set for production")
|
||||
if not settings.database_url and not (settings.db_host and settings.db_name and settings.db_user):
|
||||
issues.append("Database URL or database connection parameters must be set for production")
|
||||
|
||||
if settings.debug:
|
||||
issues.append("Debug mode should be disabled in production")
|
||||
|
||||
21
ui/README.md
21
ui/README.md
@@ -34,6 +34,12 @@ ui/
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
### Smart Backend Detection
|
||||
- **Automatic Detection**: Automatically detects if your FastAPI backend is running
|
||||
- **Real Backend Priority**: Always uses the real backend when available
|
||||
- **Mock Fallback**: Falls back to mock server only when backend is unavailable
|
||||
- **Testing Mode**: Can force mock mode for testing and development
|
||||
|
||||
### Real-time Dashboard
|
||||
- Live system health monitoring
|
||||
- Real-time pose detection statistics
|
||||
@@ -281,6 +287,14 @@ apiService.addResponseInterceptor(async (response, url) => {
|
||||
## 🚀 Deployment
|
||||
|
||||
### Development
|
||||
|
||||
**Option 1: Use the startup script**
|
||||
```bash
|
||||
cd /workspaces/wifi-densepose/ui
|
||||
./start-ui.sh
|
||||
```
|
||||
|
||||
**Option 2: Manual setup**
|
||||
```bash
|
||||
# First, start your FastAPI backend (runs on port 8000)
|
||||
wifi-densepose start
|
||||
@@ -294,9 +308,14 @@ python -m http.server 3000
|
||||
npx http-server . -p 3000
|
||||
|
||||
# Open the UI at http://localhost:3000
|
||||
# The UI will connect to the FastAPI backend at http://localhost:8000
|
||||
# The UI will automatically detect and connect to your backend
|
||||
```
|
||||
|
||||
### Backend Detection Behavior
|
||||
- **Real Backend Available**: UI connects to `http://localhost:8000` and shows ✅ "Connected to real backend"
|
||||
- **Backend Unavailable**: UI automatically uses mock server and shows ⚠️ "Mock server active - testing mode"
|
||||
- **Force Mock Mode**: Set `API_CONFIG.MOCK_SERVER.ENABLED = true` for testing
|
||||
|
||||
### Production
|
||||
1. Configure `API_CONFIG.BASE_URL` for your backend
|
||||
2. Set up HTTPS for WebSocket connections
|
||||
|
||||
54
ui/app.js
54
ui/app.js
@@ -7,6 +7,7 @@ import { LiveDemoTab } from './components/LiveDemoTab.js';
|
||||
import { apiService } from './services/api.service.js';
|
||||
import { wsService } from './services/websocket.service.js';
|
||||
import { healthService } from './services/health.service.js';
|
||||
import { backendDetector } from './utils/backend-detector.js';
|
||||
|
||||
class WiFiDensePoseApp {
|
||||
constructor() {
|
||||
@@ -51,13 +52,30 @@ class WiFiDensePoseApp {
|
||||
return response;
|
||||
});
|
||||
|
||||
// Check API availability
|
||||
try {
|
||||
const health = await healthService.checkLiveness();
|
||||
console.log('API is available:', health);
|
||||
} catch (error) {
|
||||
console.error('API is not available:', error);
|
||||
throw new Error('API is not available. Please ensure the backend is running.');
|
||||
// Detect backend availability and initialize accordingly
|
||||
const useMock = await backendDetector.shouldUseMockServer();
|
||||
|
||||
if (useMock) {
|
||||
console.log('🧪 Initializing with mock server for testing');
|
||||
// Import and start mock server only when needed
|
||||
const { mockServer } = await import('./utils/mock-server.js');
|
||||
mockServer.start();
|
||||
|
||||
// Show notification to user
|
||||
this.showBackendStatus('Mock server active - testing mode', 'warning');
|
||||
} else {
|
||||
console.log('🔌 Initializing with real backend');
|
||||
|
||||
// Verify backend is actually working
|
||||
try {
|
||||
const health = await healthService.checkLiveness();
|
||||
console.log('✅ Backend is available and responding:', health);
|
||||
this.showBackendStatus('Connected to real backend', 'success');
|
||||
} catch (error) {
|
||||
console.error('❌ Backend check failed:', error);
|
||||
this.showBackendStatus('Backend connection failed', 'error');
|
||||
// Don't throw - let the app continue and retry later
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +213,28 @@ class WiFiDensePoseApp {
|
||||
});
|
||||
}
|
||||
|
||||
// Show backend status notification
|
||||
showBackendStatus(message, type) {
|
||||
// Create status notification if it doesn't exist
|
||||
let statusToast = document.getElementById('backendStatusToast');
|
||||
if (!statusToast) {
|
||||
statusToast = document.createElement('div');
|
||||
statusToast.id = 'backendStatusToast';
|
||||
statusToast.className = 'backend-status-toast';
|
||||
document.body.appendChild(statusToast);
|
||||
}
|
||||
|
||||
statusToast.textContent = message;
|
||||
statusToast.className = `backend-status-toast ${type}`;
|
||||
statusToast.classList.add('show');
|
||||
|
||||
// Auto-hide success messages, keep warnings and errors longer
|
||||
const timeout = type === 'success' ? 3000 : 8000;
|
||||
setTimeout(() => {
|
||||
statusToast.classList.remove('show');
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
// Show global error message
|
||||
showGlobalError(message) {
|
||||
// Create error toast if it doesn't exist
|
||||
|
||||
@@ -6,6 +6,12 @@ export const API_CONFIG = {
|
||||
WS_PREFIX: 'ws://',
|
||||
WSS_PREFIX: 'wss://',
|
||||
|
||||
// Mock server configuration (only for testing)
|
||||
MOCK_SERVER: {
|
||||
ENABLED: false, // Set to true only for testing without backend
|
||||
AUTO_DETECT: true, // Automatically detect if backend is available
|
||||
},
|
||||
|
||||
// API Endpoints
|
||||
ENDPOINTS: {
|
||||
// Root & Info
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// API Service for WiFi-DensePose UI
|
||||
|
||||
import { API_CONFIG, buildApiUrl } from '../config/api.config.js';
|
||||
import { backendDetector } from '../utils/backend-detector.js';
|
||||
|
||||
export class ApiService {
|
||||
constructor() {
|
||||
@@ -69,8 +70,15 @@ export class ApiService {
|
||||
// Process request through interceptors
|
||||
const processed = await this.processRequest(url, options);
|
||||
|
||||
// Determine the correct base URL (real backend vs mock)
|
||||
let finalUrl = processed.url;
|
||||
if (processed.url.startsWith(API_CONFIG.BASE_URL)) {
|
||||
const baseUrl = await backendDetector.getBaseUrl();
|
||||
finalUrl = processed.url.replace(API_CONFIG.BASE_URL, baseUrl);
|
||||
}
|
||||
|
||||
// Make the request
|
||||
const response = await fetch(processed.url, {
|
||||
const response = await fetch(finalUrl, {
|
||||
...processed.options,
|
||||
headers: this.getHeaders(processed.options.headers)
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// WebSocket Service for WiFi-DensePose UI
|
||||
|
||||
import { API_CONFIG, buildWsUrl } from '../config/api.config.js';
|
||||
import { backendDetector } from '../utils/backend-detector.js';
|
||||
|
||||
export class WebSocketService {
|
||||
constructor() {
|
||||
@@ -10,8 +11,18 @@ export class WebSocketService {
|
||||
}
|
||||
|
||||
// Connect to WebSocket endpoint
|
||||
connect(endpoint, params = {}, handlers = {}) {
|
||||
const url = buildWsUrl(endpoint, params);
|
||||
async connect(endpoint, params = {}, handlers = {}) {
|
||||
// Determine if we should use mock WebSockets
|
||||
const useMock = await backendDetector.shouldUseMockServer();
|
||||
|
||||
let url;
|
||||
if (useMock) {
|
||||
// Use mock WebSocket URL (served from same origin as UI)
|
||||
url = buildWsUrl(endpoint, params).replace('localhost:8000', window.location.host);
|
||||
} else {
|
||||
// Use real backend WebSocket URL
|
||||
url = buildWsUrl(endpoint, params);
|
||||
}
|
||||
|
||||
// Check if already connected
|
||||
if (this.connections.has(url)) {
|
||||
|
||||
36
ui/style.css
36
ui/style.css
@@ -1573,6 +1573,42 @@ canvas {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Backend status toast */
|
||||
.backend-status-toast {
|
||||
position: fixed;
|
||||
top: var(--space-24);
|
||||
right: var(--space-24);
|
||||
padding: var(--space-12) var(--space-20);
|
||||
border-radius: var(--radius-base);
|
||||
box-shadow: var(--shadow-lg);
|
||||
transform: translateY(-100%);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
z-index: 1001;
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.backend-status-toast.show {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.backend-status-toast.success {
|
||||
background: var(--color-success);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.backend-status-toast.warning {
|
||||
background: var(--color-warning);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.backend-status-toast.error {
|
||||
background: var(--color-error);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Tab badge */
|
||||
.tab-badge {
|
||||
display: inline-block;
|
||||
|
||||
@@ -95,8 +95,8 @@
|
||||
<!-- Test Controls Panel -->
|
||||
<div class="test-controls">
|
||||
<h3>Integration Tests</h3>
|
||||
<button class="test-button" onclick="startMockServer()">Start Mock Server</button>
|
||||
<button class="test-button danger" onclick="stopMockServer()">Stop Mock Server</button>
|
||||
<button class="test-button" onclick="toggleMockMode()">Toggle Mock Mode</button>
|
||||
<button class="test-button" onclick="checkBackendStatus()">Check Backend Status</button>
|
||||
<button class="test-button" onclick="testHealthAPI()">Test Health API</button>
|
||||
<button class="test-button" onclick="testPoseAPI()">Test Pose API</button>
|
||||
<button class="test-button" onclick="testWebSocketStream()">Test WebSocket</button>
|
||||
@@ -376,34 +376,60 @@
|
||||
<script type="module">
|
||||
import { mockServer } from '../utils/mock-server.js';
|
||||
import { WiFiDensePoseApp } from '../app.js';
|
||||
import { API_CONFIG } from '../config/api.config.js';
|
||||
import { backendDetector } from '../utils/backend-detector.js';
|
||||
|
||||
// Global test functions
|
||||
window.mockServer = mockServer;
|
||||
window.app = null;
|
||||
|
||||
window.startMockServer = () => {
|
||||
window.toggleMockMode = async () => {
|
||||
try {
|
||||
mockServer.start();
|
||||
updateMockIndicator(true);
|
||||
showTestStatus('Mock server started successfully', 'success');
|
||||
// Toggle mock mode
|
||||
API_CONFIG.MOCK_SERVER.ENABLED = !API_CONFIG.MOCK_SERVER.ENABLED;
|
||||
|
||||
// Initialize app if not already done
|
||||
// Force backend detector to recheck
|
||||
backendDetector.forceCheck();
|
||||
|
||||
if (API_CONFIG.MOCK_SERVER.ENABLED) {
|
||||
mockServer.start();
|
||||
updateMockIndicator(true);
|
||||
showTestStatus('Mock mode enabled - using test data', 'success');
|
||||
} else {
|
||||
mockServer.stop();
|
||||
updateMockIndicator(false);
|
||||
showTestStatus('Mock mode disabled - using real backend', 'info');
|
||||
}
|
||||
|
||||
// Reinitialize app with new configuration
|
||||
if (!window.app) {
|
||||
window.app = new WiFiDensePoseApp();
|
||||
window.app.init();
|
||||
await window.app.init();
|
||||
}
|
||||
} catch (error) {
|
||||
showTestStatus(`Failed to start mock server: ${error.message}`, 'error');
|
||||
showTestStatus(`Failed to toggle mock mode: ${error.message}`, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.stopMockServer = () => {
|
||||
window.checkBackendStatus = async () => {
|
||||
try {
|
||||
mockServer.stop();
|
||||
updateMockIndicator(false);
|
||||
showTestStatus('Mock server stopped', 'info');
|
||||
showTestStatus('Checking backend status...', 'info');
|
||||
|
||||
const isAvailable = await backendDetector.checkBackendAvailability();
|
||||
const useMock = await backendDetector.shouldUseMockServer();
|
||||
|
||||
if (isAvailable && !useMock) {
|
||||
showTestStatus('✅ Real backend is available and being used', 'success');
|
||||
updateMockIndicator(false);
|
||||
} else if (useMock) {
|
||||
showTestStatus('🧪 Using mock server (testing mode)', 'success');
|
||||
updateMockIndicator(true);
|
||||
} else {
|
||||
showTestStatus('❌ Backend unavailable, mock server available', 'error');
|
||||
updateMockIndicator(false);
|
||||
}
|
||||
} catch (error) {
|
||||
showTestStatus(`Failed to stop mock server: ${error.message}`, 'error');
|
||||
showTestStatus(`Backend check failed: ${error.message}`, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -537,9 +563,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-start mock server on load
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
startMockServer();
|
||||
// Auto-check backend status on load
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
await checkBackendStatus();
|
||||
|
||||
// Initialize app
|
||||
if (!window.app) {
|
||||
window.app = new WiFiDensePoseApp();
|
||||
await window.app.init();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
101
ui/utils/backend-detector.js
Normal file
101
ui/utils/backend-detector.js
Normal file
@@ -0,0 +1,101 @@
|
||||
// Backend Detection Utility
|
||||
|
||||
import { API_CONFIG } from '../config/api.config.js';
|
||||
|
||||
export class BackendDetector {
|
||||
constructor() {
|
||||
this.isBackendAvailable = null;
|
||||
this.lastCheck = 0;
|
||||
this.checkInterval = 30000; // Check every 30 seconds
|
||||
}
|
||||
|
||||
// Check if the real backend is available
|
||||
async checkBackendAvailability() {
|
||||
const now = Date.now();
|
||||
|
||||
// Use cached result if recent
|
||||
if (this.isBackendAvailable !== null && (now - this.lastCheck) < this.checkInterval) {
|
||||
return this.isBackendAvailable;
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🔍 Checking backend availability...');
|
||||
|
||||
// Try to connect to the health endpoint with a short timeout
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 3000); // 3 second timeout
|
||||
|
||||
const response = await fetch(`${API_CONFIG.BASE_URL}/health/live`, {
|
||||
method: 'GET',
|
||||
signal: controller.signal,
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (response.ok) {
|
||||
this.isBackendAvailable = true;
|
||||
this.lastCheck = now;
|
||||
console.log('✅ Real backend is available');
|
||||
return true;
|
||||
} else {
|
||||
throw new Error(`Backend responded with status ${response.status}`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.isBackendAvailable = false;
|
||||
this.lastCheck = now;
|
||||
|
||||
if (error.name === 'AbortError') {
|
||||
console.log('⏱️ Backend check timed out - assuming unavailable');
|
||||
} else {
|
||||
console.log(`❌ Backend unavailable: ${error.message}`);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if mock server should be used
|
||||
async shouldUseMockServer() {
|
||||
// If mock is explicitly enabled, always use it
|
||||
if (API_CONFIG.MOCK_SERVER.ENABLED) {
|
||||
console.log('🧪 Using mock server (explicitly enabled)');
|
||||
return true;
|
||||
}
|
||||
|
||||
// If auto-detection is disabled, never use mock
|
||||
if (!API_CONFIG.MOCK_SERVER.AUTO_DETECT) {
|
||||
console.log('🔌 Using real backend (auto-detection disabled)');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if backend is available
|
||||
const backendAvailable = await this.checkBackendAvailability();
|
||||
|
||||
if (backendAvailable) {
|
||||
console.log('🔌 Using real backend (detected and available)');
|
||||
return false;
|
||||
} else {
|
||||
console.log('🧪 Using mock server (backend unavailable)');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the appropriate base URL
|
||||
async getBaseUrl() {
|
||||
const useMock = await this.shouldUseMockServer();
|
||||
return useMock ? window.location.origin : API_CONFIG.BASE_URL;
|
||||
}
|
||||
|
||||
// Force a fresh check
|
||||
forceCheck() {
|
||||
this.isBackendAvailable = null;
|
||||
this.lastCheck = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Create singleton instance
|
||||
export const backendDetector = new BackendDetector();
|
||||
Reference in New Issue
Block a user