Add Dangerous Pi MVP implementation - complete backend and system integration

This commit adds the complete Dangerous Pi web management interface with all MVP features implemented and tested locally.

## New Features

### Backend (Python + FastAPI)
- Complete FastAPI backend with async support
- 40+ API endpoints (Health, PM3, WiFi, Updates, UPS, BLE, Plugins)
- 6 managers: Session, WiFi, Update, UPS, BLE, Plugin
- SQLite database with sessions, config, history, crash reports
- Server-Sent Events (SSE) for real-time notifications
- Mock PM3 worker for development without hardware

### WiFi Manager
- Interface detection (USB vs built-in)
- Network scanning with signal strength
- Mode switching (AP/Client/Dual/Auto/Off)
- Network connection with password support
- Hidden SSID and saved networks support
- Static IP and DHCP configuration
- 10 WiFi API endpoints

### Update Manager
- GitHub releases API integration
- Automatic periodic update checks
- Semantic version comparison
- Update download with progress tracking
- SHA256 checksum verification
- Automatic installation with backup and rollback
- PM3 client rebuild after updates
- 6 Update API endpoints

### UPS Manager
- I2C battery monitoring (MAX17040-compatible)
- Battery percentage, voltage, current tracking
- Power source detection (AC/Battery)
- Safe shutdown triggers at configurable thresholds
- Event callbacks for battery warnings
- SSE and BLE notification integration
- 3 UPS API endpoints

### BLE Manager
- Bluetooth Low Energy notification support
- Auto-detects BLE capability
- Multiple notification types (updates, battery, shutdown, etc.)
- BLE advertising management
- Device connection tracking
- 4 BLE API endpoints

### Plugin Framework
- Dynamic plugin loading/unloading
- Plugin lifecycle management (load, enable, disable, unload)
- Hook system for extensibility
- JSON-based metadata
- Example "Hello World" plugin included
- 7 Plugin API endpoints

### Frontend (Remix.js + React)
- Cyberpunk-themed responsive UI
- Dashboard with system status
- PM3 command interface with history
- Settings page with WiFi and Update management
- Command logs viewer
- Theme toggle (Dark/Light/Auto)
- Server-side rendering (SSR)
- Mobile-first responsive design

### System Integration
- Systemd service with security hardening
- Automated install/uninstall scripts
- Environment configuration template
- Hardware access groups (i2c, bluetooth, gpio, dialout)
- Pi-gen stage 04 integration for OS image building
- Port conflict resolution with ttyd-bash
- I2C interface auto-enable for UPS HAT

### Testing
- test_backend.py - Backend API tests
- test_ups.py - UPS manager tests
- test_ble.py - BLE manager tests
- test_plugins.py - Plugin manager tests
- All tests passing locally

### Documentation
- 12 comprehensive documentation files
- claude.md - AI development guide
- WIFI_MANAGER.md - WiFi management guide
- UPDATE_MANAGER.md - Update system guide
- PORT_CONFLICT.md - Port conflict resolution guide
- MVP_COMPLETE.md - MVP implementation summary
- PROJECT_STATUS.md - Project status and roadmap
- systemd/README.md - Service management docs
- pi-gen integration documentation

## Technical Details
- ~5,000+ lines of backend code
- 11 Python dependencies (smbus2 added for UPS)
- FastAPI with async/await throughout
- Type hints and docstrings on all functions
- RESTful API design with SSE for notifications
- Security hardening (non-root, protected dirs, resource limits)

## Next Steps
- Deploy to Raspberry Pi Zero 2 W hardware
- Test with real Proxmark3 device
- Test UPS HAT integration
- Test BLE on Pi hardware
- Build custom OS image with pi-gen
- Performance optimization for Pi Zero 2 W

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
michael
2025-11-26 08:11:36 -08:00
parent 0a586c5360
commit 1da6730735
68 changed files with 12673 additions and 5 deletions

185
app/backend/api/updates.py Normal file
View File

@@ -0,0 +1,185 @@
"""Update management API endpoints."""
from typing import Optional
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
from ..managers.update_manager import get_update_manager, UpdateStatus
from ..managers.ble_manager import get_ble_manager, NotificationType
router = APIRouter()
class UpdateCheckResponse(BaseModel):
"""Response model for update check."""
update_available: bool
current_version: str
latest_version: Optional[str] = None
release_date: Optional[str] = None
changelog: Optional[str] = None
is_prerelease: bool = False
download_size: Optional[int] = None
message: Optional[str] = None
class UpdateProgressResponse(BaseModel):
"""Response model for update progress."""
status: str
current_version: str
available_version: Optional[str] = None
download_progress: float = 0.0
error_message: Optional[str] = None
last_check: Optional[str] = None
class ReleaseNotesRequest(BaseModel):
"""Request model for release notes."""
version: Optional[str] = None
@router.get("/check", response_model=UpdateCheckResponse)
async def check_for_updates():
"""Check for available updates.
Returns:
UpdateCheckResponse with update status and info
"""
try:
manager = get_update_manager()
ble_manager = get_ble_manager()
result = await manager.check_for_updates()
# Send BLE notification if update is available
if result.get("update_available"):
await ble_manager.send_notification(
NotificationType.UPDATE_AVAILABLE,
f"Update available: v{result['latest_version']}",
{"version": result["latest_version"]}
)
return UpdateCheckResponse(**result)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/progress", response_model=UpdateProgressResponse)
async def get_update_progress():
"""Get current update progress.
Returns:
UpdateProgressResponse with current status
"""
try:
manager = get_update_manager()
progress = await manager.get_progress()
return UpdateProgressResponse(
status=progress.status.value,
current_version=progress.current_version,
available_version=progress.available_version,
download_progress=progress.download_progress,
error_message=progress.error_message,
last_check=progress.last_check
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/download")
async def download_update():
"""Download the available update.
Returns:
Success message
"""
try:
manager = get_update_manager()
success = await manager.download_update()
if success:
return {"message": "Update downloaded successfully"}
else:
raise HTTPException(status_code=500, detail="Download failed")
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/install")
async def install_update():
"""Install the downloaded update.
Returns:
Success message
"""
try:
manager = get_update_manager()
ble_manager = get_ble_manager()
success = await manager.install_update()
if success:
# Send BLE notification
await ble_manager.send_notification(
NotificationType.UPDATE_COMPLETE,
"Update installed successfully",
{"restart_required": True}
)
return {
"message": "Update installed successfully. Please restart the service.",
"restart_required": True
}
else:
raise HTTPException(status_code=500, detail="Installation failed")
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.post("/release-notes", response_model=dict)
async def get_release_notes(request: ReleaseNotesRequest):
"""Get release notes for a specific version.
Args:
request: Version to get notes for (latest if not specified)
Returns:
Release notes as markdown
"""
try:
manager = get_update_manager()
notes = await manager.get_release_notes(request.version)
return {
"version": request.version or "latest",
"notes": notes
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/current-version")
async def get_current_version():
"""Get current system version.
Returns:
Current version info
"""
try:
manager = get_update_manager()
progress = await manager.get_progress()
return {
"version": progress.current_version,
"last_check": progress.last_check
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))