feat: Geutebruck GeViScope/GeViSoft Action Mapping System - MVP
This MVP release provides a complete full-stack solution for managing action mappings in Geutebruck's GeViScope and GeViSoft video surveillance systems. ## Features ### Flutter Web Application (Port 8081) - Modern, responsive UI for managing action mappings - Action picker dialog with full parameter configuration - Support for both GSC (GeViScope) and G-Core server actions - Consistent UI for input and output actions with edit/delete capabilities - Real-time action mapping creation, editing, and deletion - Server categorization (GSC: prefix for GeViScope, G-Core: prefix for G-Core servers) ### FastAPI REST Backend (Port 8000) - RESTful API for action mapping CRUD operations - Action template service with comprehensive action catalog (247 actions) - Server management (G-Core and GeViScope servers) - Configuration tree reading and writing - JWT authentication with role-based access control - PostgreSQL database integration ### C# SDK Bridge (gRPC, Port 50051) - Native integration with GeViSoft SDK (GeViProcAPINET_4_0.dll) - Action mapping creation with correct binary format - Support for GSC and G-Core action types - Proper Camera parameter inclusion in action strings (fixes CrossSwitch bug) - Action ID lookup table with server-specific action IDs - Configuration reading/writing via SetupClient ## Bug Fixes - **CrossSwitch Bug**: GSC and G-Core actions now correctly display camera/PTZ head parameters in GeViSet - Action strings now include Camera parameter: `@ PanLeft (Comment: "", Camera: 101028)` - Proper filter flags and VideoInput=0 for action mappings - Correct action ID assignment (4198 for GSC, 9294 for G-Core PanLeft) ## Technical Stack - **Frontend**: Flutter Web, Dart, Dio HTTP client - **Backend**: Python FastAPI, PostgreSQL, Redis - **SDK Bridge**: C# .NET 8.0, gRPC, GeViSoft SDK - **Authentication**: JWT tokens - **Configuration**: GeViSoft .set files (binary format) ## Credentials - GeViSoft/GeViScope: username=sysadmin, password=masterkey - Default admin: username=admin, password=admin123 ## Deployment All services run on localhost: - Flutter Web: http://localhost:8081 - FastAPI: http://localhost:8000 - SDK Bridge gRPC: localhost:50051 - GeViServer: localhost (default port) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
264
geutebruck-api/specs/001-flutter-app/README.md
Normal file
264
geutebruck-api/specs/001-flutter-app/README.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# Flutter App Specification - 001-flutter-app
|
||||
|
||||
## Overview
|
||||
|
||||
This specification defines a mobile application for managing Geutebruck video surveillance systems through the REST API. The app provides administrators and operators with full control over server configurations, action mappings, cameras, monitors, and cross-switching operations.
|
||||
|
||||
## Specification Documents
|
||||
|
||||
### 📜 [constitution.md](./constitution.md)
|
||||
**Foundational principles and standards**
|
||||
|
||||
Defines the core principles, architecture patterns, testing standards, and code quality requirements for the Flutter app development. This document must be reviewed and understood by all team members before beginning implementation.
|
||||
|
||||
**Key Topics:**
|
||||
- Clean Architecture + BLoC pattern
|
||||
- Testing requirements (80% coverage minimum)
|
||||
- Security standards (secure storage, HTTPS, token management)
|
||||
- Performance budgets
|
||||
- Code organization and style guidelines
|
||||
|
||||
---
|
||||
|
||||
### 📋 [spec.md](./spec.md)
|
||||
**Functional requirements and user stories**
|
||||
|
||||
Contains all user stories organized by epic, with detailed acceptance criteria for each feature. This is the primary reference for understanding WHAT needs to be built and HOW it should behave from a user perspective.
|
||||
|
||||
**Epics Covered:**
|
||||
1. Authentication & Authorization (3 user stories)
|
||||
2. Server Management (8 user stories)
|
||||
3. Action Mapping Management (5 user stories)
|
||||
4. Camera Management (3 user stories)
|
||||
5. Monitor Management (2 user stories)
|
||||
6. Cross-Switching (2 user stories)
|
||||
7. Configuration Management (2 user stories)
|
||||
8. User Interface & Navigation (4 user stories)
|
||||
|
||||
**Total:** 29 user stories with complete acceptance criteria
|
||||
|
||||
---
|
||||
|
||||
### 🏗️ [plan.md](./plan.md)
|
||||
**Technical implementation strategy**
|
||||
|
||||
Describes the technical architecture, technology stack, design patterns, and implementation approach. This document explains HOW the system will be built from a technical perspective.
|
||||
|
||||
**Key Sections:**
|
||||
- Technology stack with justifications
|
||||
- Clean Architecture layered approach
|
||||
- BLoC state management pattern
|
||||
- Folder structure and organization
|
||||
- API integration strategy
|
||||
- Caching and offline support
|
||||
- Error handling patterns
|
||||
- Testing strategy
|
||||
- Performance optimization techniques
|
||||
|
||||
---
|
||||
|
||||
### ✅ [tasks.md](./tasks.md)
|
||||
**Detailed implementation task breakdown**
|
||||
|
||||
Provides a comprehensive, ordered list of implementation tasks organized by user story and phase. Each task includes file paths, dependencies, and test requirements.
|
||||
|
||||
**Phases:**
|
||||
1. Foundation & Setup
|
||||
2. Server Management
|
||||
3. Action Mapping Management
|
||||
4. Camera Management
|
||||
5. Monitor & Cross-Switching
|
||||
6. Configuration Management
|
||||
7. UI & Navigation
|
||||
8. Testing & Polish
|
||||
9. Deployment Preparation
|
||||
|
||||
**Total:** 186+ tasks with dependencies mapped
|
||||
|
||||
---
|
||||
|
||||
### 🚀 [quickstart.md](./quickstart.md)
|
||||
**Setup and running instructions**
|
||||
|
||||
Step-by-step guide for setting up the development environment, installing dependencies, running the app, and common development workflows.
|
||||
|
||||
**Covers:**
|
||||
- Prerequisites and installation
|
||||
- Running the app on different platforms
|
||||
- Development workflow
|
||||
- Testing commands
|
||||
- Troubleshooting
|
||||
- IDE setup
|
||||
- CI/CD configuration
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
### For Product Owners / Stakeholders
|
||||
|
||||
1. Start with **spec.md** to review user stories and acceptance criteria
|
||||
2. Use **constitution.md** to understand quality standards
|
||||
3. Review **plan.md** for technical approach and timeline estimates
|
||||
|
||||
### For Developers
|
||||
|
||||
1. Read **constitution.md** to understand coding standards
|
||||
2. Study **plan.md** for architecture and patterns
|
||||
3. Follow **quickstart.md** to set up your environment
|
||||
4. Use **tasks.md** to pick up tasks based on current phase
|
||||
5. Reference **spec.md** for acceptance criteria while implementing
|
||||
|
||||
### For Project Managers
|
||||
|
||||
1. Use **tasks.md** for sprint planning and task assignment
|
||||
2. Track progress against user stories in **spec.md**
|
||||
3. Monitor adherence to **constitution.md** standards during code review
|
||||
4. Reference **plan.md** for understanding technical dependencies
|
||||
|
||||
## Document Relationships
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ constitution.md │ ◄─── Defines standards for all documents
|
||||
└─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ spec.md │ ◄─── What needs to be built (User Stories)
|
||||
└─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ plan.md │ ◄─── How it will be built (Architecture)
|
||||
└─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ tasks.md │ ◄─── Detailed task breakdown
|
||||
└─────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────┐
|
||||
│ quickstart.md │ ◄─── How to get started
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
## Current Status
|
||||
|
||||
**Specification Status:** ✅ Complete
|
||||
|
||||
All specification documents have been created and reviewed. Ready for implementation.
|
||||
|
||||
**Implementation Status:** 🚧 Not Started
|
||||
|
||||
Awaiting Flutter SDK installation completion and development environment setup.
|
||||
|
||||
## Implementation Workflow
|
||||
|
||||
Following the spec-kit methodology:
|
||||
|
||||
```
|
||||
1. Constitution (Standards) ✅ Complete
|
||||
2. Specification (Requirements) ✅ Complete
|
||||
3. Clarification (Q&A) ⏳ Ongoing
|
||||
4. Plan (Architecture) ✅ Complete
|
||||
5. Tasks (Breakdown) ✅ Complete
|
||||
6. Implementation 🚧 Ready to start
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
The Flutter app integrates with the Geutebruck REST API:
|
||||
|
||||
**Base URL:** `http://localhost:8000/api/v1`
|
||||
|
||||
**Key Endpoints:**
|
||||
- Authentication: `/auth/login`, `/auth/refresh`
|
||||
- Servers: `/configuration/servers/gcore`, `/configuration/servers/geviscope`
|
||||
- Action Mappings: `/configuration/action-mappings`
|
||||
- Cameras: `/cameras`
|
||||
- Monitors: `/monitors`
|
||||
- Cross-Switching: `/crossswitch`
|
||||
|
||||
See the API documentation at `http://localhost:8000/docs` for complete endpoint details.
|
||||
|
||||
## Technology Stack Summary
|
||||
|
||||
- **Framework:** Flutter 3.24+
|
||||
- **Language:** Dart 3.0+
|
||||
- **State Management:** BLoC (flutter_bloc)
|
||||
- **HTTP Client:** Dio + Retrofit
|
||||
- **Local Storage:** Hive + flutter_secure_storage
|
||||
- **Dependency Injection:** get_it + injectable
|
||||
- **Code Generation:** freezed, json_serializable, build_runner
|
||||
- **Testing:** mockito, bloc_test, integration_test
|
||||
|
||||
## Success Criteria
|
||||
|
||||
The implementation will be considered successful when:
|
||||
|
||||
- [ ] All 29 user stories implemented with acceptance criteria met
|
||||
- [ ] Test coverage ≥ 80%
|
||||
- [ ] All widget tests passing
|
||||
- [ ] Integration tests for critical flows passing
|
||||
- [ ] Performance benchmarks met (startup < 3s, 60 FPS scrolling)
|
||||
- [ ] Security review completed
|
||||
- [ ] Accessibility tested
|
||||
- [ ] User acceptance testing completed
|
||||
|
||||
## Timeline Estimate
|
||||
|
||||
Based on the task breakdown in tasks.md:
|
||||
|
||||
- **Phase 1 (Foundation):** 1-2 weeks
|
||||
- **Phase 2 (Server Management):** 1-2 weeks
|
||||
- **Phase 3 (Action Mappings):** 1-2 weeks
|
||||
- **Phase 4 (Cameras):** 1-2 weeks
|
||||
- **Phase 5 (Monitors & Cross-Switching):** 1-2 weeks
|
||||
- **Phase 6 (Configuration):** 1 week
|
||||
- **Phase 7 (UI & Navigation):** 1 week
|
||||
- **Phase 8 (Testing & Polish):** 2 weeks
|
||||
- **Phase 9 (Deployment):** 1 week
|
||||
|
||||
**Total:** 10-13 weeks (2.5-3 months) with 2-3 developers
|
||||
|
||||
## Team Roles
|
||||
|
||||
**Recommended Team:**
|
||||
- 1 Senior Flutter Developer (Architecture, Code Review)
|
||||
- 2 Flutter Developers (Feature Implementation)
|
||||
- 1 QA Engineer (Testing)
|
||||
- 1 UI/UX Designer (Designs and Assets)
|
||||
- 1 Product Owner (Requirements, Acceptance)
|
||||
|
||||
## Maintenance & Updates
|
||||
|
||||
This specification is a living document. Updates should be made when:
|
||||
- New features are requested
|
||||
- Technical architecture changes
|
||||
- API endpoints are modified
|
||||
- User feedback requires adjustments
|
||||
|
||||
**Version Control:**
|
||||
- All changes tracked in Git
|
||||
- Each major update creates a new version tag
|
||||
- Breaking changes documented in CHANGELOG.md
|
||||
|
||||
## Questions or Clarifications
|
||||
|
||||
For questions about the specification:
|
||||
1. Check the relevant document (constitution, spec, plan, tasks)
|
||||
2. Review the quickstart guide for setup/development questions
|
||||
3. Consult the team lead for architectural decisions
|
||||
4. Create an issue in the project repository for tracking
|
||||
|
||||
## License
|
||||
|
||||
This specification is proprietary to the Geutebruck API project.
|
||||
|
||||
---
|
||||
|
||||
**Specification Version:** 1.0
|
||||
**Last Updated:** December 19, 2025
|
||||
**Status:** Ready for Implementation
|
||||
142
geutebruck-api/specs/001-flutter-app/constitution.md
Normal file
142
geutebruck-api/specs/001-flutter-app/constitution.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# Flutter App Constitution
|
||||
|
||||
## Purpose
|
||||
|
||||
This document establishes the foundational principles and standards for developing the Geutebruck API Flutter mobile application. These guidelines ensure code quality, maintainability, and exceptional user experience.
|
||||
|
||||
## Core Principles
|
||||
|
||||
### 1. Code Quality
|
||||
|
||||
- **Clean Code**: Follow Flutter and Dart style guides (effective_dart)
|
||||
- **Modularity**: Organize code into reusable widgets and services
|
||||
- **Separation of Concerns**: Implement clear boundaries between UI, business logic, and data layers
|
||||
- **DRY Principle**: Avoid code duplication through proper abstraction
|
||||
- **SOLID Principles**: Apply object-oriented design principles where appropriate
|
||||
|
||||
### 2. Architecture
|
||||
|
||||
- **Pattern**: Use **BLoC (Business Logic Component)** pattern for state management
|
||||
- Separates presentation from business logic
|
||||
- Testable and predictable state management
|
||||
- Reactive programming with streams
|
||||
- **Layered Architecture**:
|
||||
- **Presentation Layer**: Widgets and UI components
|
||||
- **Business Logic Layer**: BLoCs and Cubits
|
||||
- **Data Layer**: Repositories and data sources
|
||||
- **Domain Layer**: Models and business entities
|
||||
|
||||
### 3. Testing Standards
|
||||
|
||||
- **Test Coverage**: Minimum 80% code coverage
|
||||
- **Test Types**:
|
||||
- **Unit Tests**: All business logic, repositories, and utilities
|
||||
- **Widget Tests**: All custom widgets and screens
|
||||
- **Integration Tests**: Critical user flows
|
||||
- **Test-Driven Development (TDD)**: Write tests before implementation where feasible
|
||||
- **Mocking**: Use mockito for dependency injection in tests
|
||||
|
||||
### 4. User Experience
|
||||
|
||||
- **Material Design 3**: Follow Material Design guidelines for consistency
|
||||
- **Responsive Design**: Support multiple screen sizes (phones, tablets)
|
||||
- **Accessibility**: Support screen readers, proper contrast ratios, semantic labels
|
||||
- **Performance**:
|
||||
- App startup time < 3 seconds
|
||||
- List scrolling at 60 FPS
|
||||
- Image loading with progressive rendering
|
||||
- Efficient API calls with caching
|
||||
- **Offline-First**: Cache data locally, sync when online
|
||||
- **Error Handling**: Graceful error messages with retry options
|
||||
|
||||
### 5. Security
|
||||
|
||||
- **Secure Storage**: Use flutter_secure_storage for sensitive data (JWT tokens, passwords)
|
||||
- **HTTPS Only**: All API communication over TLS
|
||||
- **Token Management**: Automatic token refresh before expiration
|
||||
- **Input Validation**: Sanitize all user inputs
|
||||
- **No Hardcoded Secrets**: Use environment variables and configuration files
|
||||
|
||||
### 6. API Integration
|
||||
|
||||
- **REST Client**: Use dio package for HTTP requests
|
||||
- **Error Handling**: Standardized error parsing and user-friendly messages
|
||||
- **Retry Logic**: Automatic retry with exponential backoff for failed requests
|
||||
- **Request Cancellation**: Cancel pending requests on screen navigation
|
||||
- **Response Caching**: Implement caching strategy for frequently accessed data
|
||||
|
||||
### 7. Code Organization
|
||||
|
||||
```
|
||||
lib/
|
||||
├── core/
|
||||
│ ├── constants/
|
||||
│ ├── errors/
|
||||
│ ├── network/
|
||||
│ └── utils/
|
||||
├── data/
|
||||
│ ├── models/
|
||||
│ ├── repositories/
|
||||
│ └── data_sources/
|
||||
├── domain/
|
||||
│ ├── entities/
|
||||
│ └── repositories/
|
||||
├── presentation/
|
||||
│ ├── blocs/
|
||||
│ ├── screens/
|
||||
│ └── widgets/
|
||||
└── main.dart
|
||||
```
|
||||
|
||||
### 8. Dependency Management
|
||||
|
||||
- **Minimal Dependencies**: Only add well-maintained, popular packages
|
||||
- **Version Locking**: Use exact versions in pubspec.yaml
|
||||
- **Regular Updates**: Review and update dependencies monthly
|
||||
- **Null Safety**: Enforce sound null safety
|
||||
|
||||
### 9. Documentation
|
||||
|
||||
- **Code Comments**: Document complex logic and non-obvious decisions
|
||||
- **API Documentation**: Generate documentation using dartdoc
|
||||
- **README**: Comprehensive setup and running instructions
|
||||
- **Change Log**: Document all changes in CHANGELOG.md
|
||||
|
||||
### 10. Version Control
|
||||
|
||||
- **Git Flow**: Use feature branches with descriptive names
|
||||
- **Commit Messages**: Follow conventional commits format
|
||||
- **Pull Requests**: Require code review before merging
|
||||
- **CI/CD**: Automated testing and deployment pipelines
|
||||
|
||||
## Governance
|
||||
|
||||
### Technical Decisions
|
||||
|
||||
- Architecture changes require team consensus
|
||||
- New dependencies require justification and approval
|
||||
- Breaking changes require migration plan
|
||||
|
||||
### Code Review Standards
|
||||
|
||||
- All code must be reviewed before merging
|
||||
- Reviewers check for:
|
||||
- Adherence to principles
|
||||
- Test coverage
|
||||
- Code clarity and documentation
|
||||
- Performance implications
|
||||
|
||||
### Performance Budgets
|
||||
|
||||
- App size: < 50MB
|
||||
- Memory usage: < 200MB during normal operation
|
||||
- Network requests: Batched and optimized
|
||||
- Battery consumption: Minimal background activity
|
||||
|
||||
## Exceptions
|
||||
|
||||
Exceptions to these principles require:
|
||||
1. Clear justification
|
||||
2. Documentation of trade-offs
|
||||
3. Approval from technical lead
|
||||
4. Technical debt tracking
|
||||
618
geutebruck-api/specs/001-flutter-app/plan.md
Normal file
618
geutebruck-api/specs/001-flutter-app/plan.md
Normal file
@@ -0,0 +1,618 @@
|
||||
# Geutebruck API Flutter App - Technical Implementation Plan
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Core Framework
|
||||
- **Flutter 3.24+**: Cross-platform mobile framework
|
||||
- **Dart 3.0+**: Programming language with sound null safety
|
||||
|
||||
### State Management
|
||||
- **flutter_bloc 8.1+**: BLoC pattern implementation
|
||||
- *Rationale*: Predictable state management, excellent testing support, separation of concerns
|
||||
- *Alternatives considered*: Provider (simpler but less structured), Riverpod (newer but less mature ecosystem)
|
||||
|
||||
### HTTP Client & API
|
||||
- **dio 5.4+**: HTTP client for API calls
|
||||
- Features: Interceptors, request/response transformation, timeout handling
|
||||
- Better than http package: More features, better error handling
|
||||
- **retrofit 4.0+**: Type-safe HTTP client generator
|
||||
- Auto-generates API client code from interface definitions
|
||||
- Reduces boilerplate and errors
|
||||
|
||||
### Data Persistence
|
||||
- **flutter_secure_storage 9.0+**: Secure storage for tokens and credentials
|
||||
- **shared_preferences 2.2+**: App settings and preferences
|
||||
- **hive 2.2+**: Local database for caching
|
||||
- *Rationale*: Fast, lightweight, no SQL required, perfect for caching API responses
|
||||
|
||||
### Dependency Injection
|
||||
- **get_it 7.6+**: Service locator pattern
|
||||
- *Rationale*: Simple, explicit dependencies, excellent for testing
|
||||
- **injectable 2.3+**: Code generation for get_it
|
||||
- Reduces boilerplate in dependency registration
|
||||
|
||||
### UI Components
|
||||
- **Material Design 3**: Modern, accessible UI components
|
||||
- **cached_network_image 3.3+**: Efficient image loading and caching
|
||||
- **shimmer 3.0+**: Loading skeletons
|
||||
- **flutter_svg 2.0+**: SVG image support
|
||||
|
||||
### Navigation
|
||||
- **go_router 13.0+**: Declarative routing
|
||||
- *Rationale*: Deep linking support, type-safe navigation, excellent for web
|
||||
|
||||
### Form Handling & Validation
|
||||
- **flutter_form_builder 9.1+**: Dynamic form creation
|
||||
- **form_builder_validators 9.1+**: Reusable validators
|
||||
|
||||
### Testing
|
||||
- **mockito 5.4+**: Mocking dependencies
|
||||
- **bloc_test 9.1+**: Testing BLoCs
|
||||
- **golden_toolkit 0.15+**: Widget screenshot testing
|
||||
|
||||
### Code Generation
|
||||
- **freezed 2.4+**: Immutable data classes with union types
|
||||
- **json_serializable 6.7+**: JSON serialization
|
||||
- **build_runner 2.4+**: Code generation orchestrator
|
||||
|
||||
### Development Tools
|
||||
- **flutter_launcher_icons 0.13+**: App icon generation
|
||||
- **flutter_native_splash 2.3+**: Splash screen generation
|
||||
- **very_good_analysis 5.1+**: Lint rules
|
||||
|
||||
## Architecture
|
||||
|
||||
### Clean Architecture + BLoC
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Presentation Layer │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ Screens │ │ Widgets │ │ BLoCs │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Domain Layer │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ Entities │ │ Use Cases │ │ Repository │ │
|
||||
│ │ │ │ │ │ Interfaces │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Data Layer │
|
||||
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
|
||||
│ │ Models │ │Repositories│ │Data Sources│ │
|
||||
│ │ │ │ │ │ (Remote) │ │
|
||||
│ └────────────┘ └────────────┘ └────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Layer Responsibilities
|
||||
|
||||
#### Presentation Layer
|
||||
- **Screens**: Full-page views (ServerListScreen, LoginScreen, etc.)
|
||||
- **Widgets**: Reusable UI components (ServerCard, LoadingWidget, etc.)
|
||||
- **BLoCs**: Business logic controllers, emit states based on events
|
||||
|
||||
#### Domain Layer
|
||||
- **Entities**: Pure business objects (Server, ActionMapping, Camera)
|
||||
- **Use Cases**: Single-responsibility business operations (GetServers, CreateServer)
|
||||
- **Repository Interfaces**: Contracts for data access
|
||||
|
||||
#### Data Layer
|
||||
- **Models**: Data transfer objects with JSON serialization
|
||||
- **Repositories**: Implement repository interfaces, coordinate data sources
|
||||
- **Data Sources**:
|
||||
- **Remote**: API client using dio/retrofit
|
||||
- **Local**: Hive cache
|
||||
|
||||
### Folder Structure
|
||||
|
||||
```
|
||||
lib/
|
||||
├── core/
|
||||
│ ├── constants/
|
||||
│ │ ├── api_constants.dart
|
||||
│ │ ├── app_constants.dart
|
||||
│ │ └── asset_constants.dart
|
||||
│ ├── errors/
|
||||
│ │ ├── exceptions.dart
|
||||
│ │ └── failures.dart
|
||||
│ ├── network/
|
||||
│ │ ├── api_client.dart
|
||||
│ │ ├── dio_client.dart
|
||||
│ │ └── interceptors/
|
||||
│ │ ├── auth_interceptor.dart
|
||||
│ │ └── logging_interceptor.dart
|
||||
│ ├── theme/
|
||||
│ │ ├── app_theme.dart
|
||||
│ │ └── colors.dart
|
||||
│ └── utils/
|
||||
│ ├── validators.dart
|
||||
│ └── extensions.dart
|
||||
├── data/
|
||||
│ ├── models/
|
||||
│ │ ├── server_model.dart
|
||||
│ │ ├── action_mapping_model.dart
|
||||
│ │ ├── camera_model.dart
|
||||
│ │ └── auth_model.dart
|
||||
│ ├── repositories/
|
||||
│ │ ├── server_repository_impl.dart
|
||||
│ │ ├── action_mapping_repository_impl.dart
|
||||
│ │ ├── camera_repository_impl.dart
|
||||
│ │ └── auth_repository_impl.dart
|
||||
│ └── data_sources/
|
||||
│ ├── remote/
|
||||
│ │ ├── server_remote_data_source.dart
|
||||
│ │ ├── action_mapping_remote_data_source.dart
|
||||
│ │ └── auth_remote_data_source.dart
|
||||
│ └── local/
|
||||
│ ├── cache_manager.dart
|
||||
│ └── secure_storage_manager.dart
|
||||
├── domain/
|
||||
│ ├── entities/
|
||||
│ │ ├── server.dart
|
||||
│ │ ├── action_mapping.dart
|
||||
│ │ ├── camera.dart
|
||||
│ │ └── user.dart
|
||||
│ ├── repositories/
|
||||
│ │ ├── server_repository.dart
|
||||
│ │ ├── action_mapping_repository.dart
|
||||
│ │ └── auth_repository.dart
|
||||
│ └── use_cases/
|
||||
│ ├── servers/
|
||||
│ │ ├── get_servers.dart
|
||||
│ │ ├── create_server.dart
|
||||
│ │ ├── update_server.dart
|
||||
│ │ └── delete_server.dart
|
||||
│ ├── action_mappings/
|
||||
│ │ ├── get_action_mappings.dart
|
||||
│ │ └── create_action_mapping.dart
|
||||
│ └── auth/
|
||||
│ ├── login.dart
|
||||
│ ├── refresh_token.dart
|
||||
│ └── logout.dart
|
||||
├── presentation/
|
||||
│ ├── blocs/
|
||||
│ │ ├── auth/
|
||||
│ │ │ ├── auth_bloc.dart
|
||||
│ │ │ ├── auth_event.dart
|
||||
│ │ │ └── auth_state.dart
|
||||
│ │ ├── server/
|
||||
│ │ │ ├── server_bloc.dart
|
||||
│ │ │ ├── server_event.dart
|
||||
│ │ │ └── server_state.dart
|
||||
│ │ └── action_mapping/
|
||||
│ │ ├── action_mapping_bloc.dart
|
||||
│ │ ├── action_mapping_event.dart
|
||||
│ │ └── action_mapping_state.dart
|
||||
│ ├── screens/
|
||||
│ │ ├── auth/
|
||||
│ │ │ └── login_screen.dart
|
||||
│ │ ├── servers/
|
||||
│ │ │ ├── server_list_screen.dart
|
||||
│ │ │ ├── server_detail_screen.dart
|
||||
│ │ │ └── server_form_screen.dart
|
||||
│ │ ├── action_mappings/
|
||||
│ │ │ ├── action_mapping_list_screen.dart
|
||||
│ │ │ └── action_mapping_form_screen.dart
|
||||
│ │ ├── cameras/
|
||||
│ │ │ ├── camera_list_screen.dart
|
||||
│ │ │ └── camera_control_screen.dart
|
||||
│ │ └── settings/
|
||||
│ │ └── settings_screen.dart
|
||||
│ └── widgets/
|
||||
│ ├── common/
|
||||
│ │ ├── loading_widget.dart
|
||||
│ │ ├── error_widget.dart
|
||||
│ │ └── empty_state_widget.dart
|
||||
│ ├── server/
|
||||
│ │ └── server_card.dart
|
||||
│ └── action_mapping/
|
||||
│ └── action_mapping_card.dart
|
||||
├── injection.dart
|
||||
└── main.dart
|
||||
```
|
||||
|
||||
## API Integration
|
||||
|
||||
### Base Configuration
|
||||
|
||||
```dart
|
||||
class ApiConfig {
|
||||
static const String baseUrl = 'http://localhost:8000';
|
||||
static const Duration timeout = Duration(seconds: 30);
|
||||
static const Duration receiveTimeout = Duration(seconds: 30);
|
||||
}
|
||||
```
|
||||
|
||||
### Dio Setup with Interceptors
|
||||
|
||||
```dart
|
||||
@singleton
|
||||
class DioClient {
|
||||
final Dio _dio;
|
||||
|
||||
DioClient() : _dio = Dio(BaseOptions(
|
||||
baseUrl: ApiConfig.baseUrl,
|
||||
connectTimeout: ApiConfig.timeout,
|
||||
receiveTimeout: ApiConfig.receiveTimeout,
|
||||
)) {
|
||||
_dio.interceptors.addAll([
|
||||
AuthInterceptor(),
|
||||
LoggingInterceptor(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Auth Interceptor (Token Management)
|
||||
|
||||
```dart
|
||||
class AuthInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
|
||||
final token = await secureStorage.read(key: 'access_token');
|
||||
if (token != null) {
|
||||
options.headers['Authorization'] = 'Bearer $token';
|
||||
}
|
||||
handler.next(options);
|
||||
}
|
||||
|
||||
@override
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
||||
if (err.response?.statusCode == 401) {
|
||||
// Token expired, try refresh
|
||||
final refreshed = await refreshToken();
|
||||
if (refreshed) {
|
||||
// Retry original request
|
||||
return handler.resolve(await _retry(err.requestOptions));
|
||||
}
|
||||
}
|
||||
handler.next(err);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Repository Pattern Example
|
||||
|
||||
```dart
|
||||
@injectable
|
||||
class ServerRepositoryImpl implements ServerRepository {
|
||||
final ServerRemoteDataSource remoteDataSource;
|
||||
final CacheManager cacheManager;
|
||||
|
||||
ServerRepositoryImpl({
|
||||
required this.remoteDataSource,
|
||||
required this.cacheManager,
|
||||
});
|
||||
|
||||
@override
|
||||
Future<Either<Failure, List<Server>>> getServers() async {
|
||||
try {
|
||||
// Try cache first
|
||||
final cached = await cacheManager.getServers();
|
||||
if (cached != null && !cached.isExpired) {
|
||||
return Right(cached.data);
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
final servers = await remoteDataSource.getServers();
|
||||
|
||||
// Update cache
|
||||
await cacheManager.saveServers(servers);
|
||||
|
||||
return Right(servers.map((m) => m.toEntity()).toList());
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NetworkException {
|
||||
return Left(NetworkFailure());
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## State Management Flow
|
||||
|
||||
### BLoC Pattern
|
||||
|
||||
```dart
|
||||
// Event
|
||||
abstract class ServerEvent {}
|
||||
class LoadServers extends ServerEvent {}
|
||||
class CreateServer extends ServerEvent {
|
||||
final ServerCreateRequest request;
|
||||
CreateServer(this.request);
|
||||
}
|
||||
|
||||
// State
|
||||
abstract class ServerState {}
|
||||
class ServerInitial extends ServerState {}
|
||||
class ServerLoading extends ServerState {}
|
||||
class ServerLoaded extends ServerState {
|
||||
final List<Server> servers;
|
||||
ServerLoaded(this.servers);
|
||||
}
|
||||
class ServerError extends ServerState {
|
||||
final String message;
|
||||
ServerError(this.message);
|
||||
}
|
||||
|
||||
// BLoC
|
||||
class ServerBloc extends Bloc<ServerEvent, ServerState> {
|
||||
final GetServers getServers;
|
||||
final CreateServer createServer;
|
||||
|
||||
ServerBloc({
|
||||
required this.getServers,
|
||||
required this.createServer,
|
||||
}) : super(ServerInitial()) {
|
||||
on<LoadServers>(_onLoadServers);
|
||||
on<CreateServer>(_onCreateServer);
|
||||
}
|
||||
|
||||
Future<void> _onLoadServers(
|
||||
LoadServers event,
|
||||
Emitter<ServerState> emit,
|
||||
) async {
|
||||
emit(ServerLoading());
|
||||
final result = await getServers();
|
||||
result.fold(
|
||||
(failure) => emit(ServerError(failure.message)),
|
||||
(servers) => emit(ServerLoaded(servers)),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Caching Strategy
|
||||
|
||||
### Cache Layers
|
||||
|
||||
1. **Memory Cache**: In-memory Map for frequently accessed data
|
||||
2. **Disk Cache (Hive)**: Persistent storage for offline access
|
||||
3. **Secure Storage**: Encrypted storage for tokens and credentials
|
||||
|
||||
### Cache Policy
|
||||
|
||||
```dart
|
||||
class CachePolicy {
|
||||
// Short-lived cache (5 minutes)
|
||||
static const Duration shortCache = Duration(minutes: 5);
|
||||
|
||||
// Medium cache (30 minutes)
|
||||
static const Duration mediumCache = Duration(minutes: 30);
|
||||
|
||||
// Long cache (24 hours)
|
||||
static const Duration longCache = Duration(hours: 24);
|
||||
}
|
||||
|
||||
// Server list: Short cache (changes frequently)
|
||||
// Action mappings: Medium cache
|
||||
// Configuration tree: Long cache
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Error Types
|
||||
|
||||
```dart
|
||||
abstract class Failure {
|
||||
String get message;
|
||||
}
|
||||
|
||||
class NetworkFailure extends Failure {
|
||||
@override
|
||||
String get message => 'No internet connection';
|
||||
}
|
||||
|
||||
class ServerFailure extends Failure {
|
||||
final String errorMessage;
|
||||
ServerFailure(this.errorMessage);
|
||||
|
||||
@override
|
||||
String get message => errorMessage;
|
||||
}
|
||||
|
||||
class ValidationFailure extends Failure {
|
||||
final Map<String, String> errors;
|
||||
ValidationFailure(this.errors);
|
||||
|
||||
@override
|
||||
String get message => 'Validation failed';
|
||||
}
|
||||
```
|
||||
|
||||
### UI Error Display
|
||||
|
||||
```dart
|
||||
Widget buildError(Failure failure) {
|
||||
if (failure is NetworkFailure) {
|
||||
return ErrorWidget(
|
||||
message: failure.message,
|
||||
icon: Icons.wifi_off,
|
||||
action: ElevatedButton(
|
||||
onPressed: () => context.read<ServerBloc>().add(LoadServers()),
|
||||
child: Text('Retry'),
|
||||
),
|
||||
);
|
||||
}
|
||||
// ... other failure types
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```dart
|
||||
void main() {
|
||||
late ServerRepositoryImpl repository;
|
||||
late MockServerRemoteDataSource mockRemoteDataSource;
|
||||
late MockCacheManager mockCacheManager;
|
||||
|
||||
setUp(() {
|
||||
mockRemoteDataSource = MockServerRemoteDataSource();
|
||||
mockCacheManager = MockCacheManager();
|
||||
repository = ServerRepositoryImpl(
|
||||
remoteDataSource: mockRemoteDataSource,
|
||||
cacheManager: mockCacheManager,
|
||||
);
|
||||
});
|
||||
|
||||
group('getServers', () {
|
||||
test('should return cached data when cache is valid', () async {
|
||||
// Arrange
|
||||
when(mockCacheManager.getServers())
|
||||
.thenAnswer((_) async => CachedData([server1, server2]));
|
||||
|
||||
// Act
|
||||
final result = await repository.getServers();
|
||||
|
||||
// Assert
|
||||
expect(result, isA<Right<Failure, List<Server>>>());
|
||||
verifyNever(mockRemoteDataSource.getServers());
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### Widget Tests
|
||||
|
||||
```dart
|
||||
void main() {
|
||||
testWidgets('ServerListScreen displays servers', (tester) async {
|
||||
// Arrange
|
||||
final mockBloc = MockServerBloc();
|
||||
when(mockBloc.state).thenReturn(ServerLoaded([server1, server2]));
|
||||
|
||||
// Act
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: BlocProvider<ServerBloc>.value(
|
||||
value: mockBloc,
|
||||
child: ServerListScreen(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect(find.text('Server 1'), findsOneWidget);
|
||||
expect(find.text('Server 2'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Build & Deployment
|
||||
|
||||
### Build Configurations
|
||||
|
||||
```yaml
|
||||
# build.yaml
|
||||
targets:
|
||||
$default:
|
||||
builders:
|
||||
freezed:
|
||||
enabled: true
|
||||
json_serializable:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
### Environment Configuration
|
||||
|
||||
```dart
|
||||
// config.dart
|
||||
abstract class Config {
|
||||
static String get apiBaseUrl => _apiBaseUrl;
|
||||
static String _apiBaseUrl = 'http://localhost:8000';
|
||||
|
||||
static void setDevelopment() {
|
||||
_apiBaseUrl = 'http://localhost:8000';
|
||||
}
|
||||
|
||||
static void setProduction() {
|
||||
_apiBaseUrl = 'https://api.production.com';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### CI/CD Pipeline
|
||||
|
||||
```yaml
|
||||
# .github/workflows/flutter.yml
|
||||
name: Flutter CI
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: subosito/flutter-action@v2
|
||||
- run: flutter pub get
|
||||
- run: flutter analyze
|
||||
- run: flutter test --coverage
|
||||
- uses: codecov/codecov-action@v3
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Foundation (Week 1-2)
|
||||
- Project setup with dependencies
|
||||
- Folder structure
|
||||
- Dependency injection setup
|
||||
- API client configuration
|
||||
- Authentication flow
|
||||
|
||||
### Phase 2: Core Features (Week 3-4)
|
||||
- Server management (list, create, update, delete)
|
||||
- Action mapping management
|
||||
- Camera list and details
|
||||
|
||||
### Phase 3: Advanced Features (Week 5-6)
|
||||
- PTZ camera control
|
||||
- Monitor management
|
||||
- Cross-switching
|
||||
- Configuration export
|
||||
|
||||
### Phase 4: Polish (Week 7-8)
|
||||
- Offline support
|
||||
- Error handling improvements
|
||||
- Performance optimization
|
||||
- UI/UX refinements
|
||||
- Accessibility improvements
|
||||
|
||||
### Phase 5: Testing & Deployment (Week 9-10)
|
||||
- Comprehensive testing
|
||||
- User acceptance testing
|
||||
- Bug fixes
|
||||
- App store preparation
|
||||
- Documentation
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Image Loading
|
||||
- Use `cached_network_image` with disk and memory cache
|
||||
- Progressive JPEG for large images
|
||||
- Thumbnail generation for lists
|
||||
|
||||
### List Performance
|
||||
- Use `ListView.builder` for long lists
|
||||
- Implement pagination for server/mapping lists
|
||||
- Lazy loading of details
|
||||
|
||||
### Memory Management
|
||||
- Dispose BLoCs and controllers properly
|
||||
- Clear cache periodically
|
||||
- Monitor memory usage in DevTools
|
||||
|
||||
### Network Optimization
|
||||
- Batch API requests where possible
|
||||
- Implement request debouncing for search
|
||||
- Cancel pending requests on navigation
|
||||
- Use HTTP/2 for multiplexing
|
||||
583
geutebruck-api/specs/001-flutter-app/quickstart.md
Normal file
583
geutebruck-api/specs/001-flutter-app/quickstart.md
Normal file
@@ -0,0 +1,583 @@
|
||||
# Geutebruck API Flutter App - Quick Start Guide
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, ensure you have the following installed:
|
||||
|
||||
### Required Software
|
||||
|
||||
1. **Flutter SDK 3.24+**
|
||||
- Download from: https://flutter.dev/docs/get-started/install
|
||||
- Add to PATH: `C:\Users\{username}\develop\flutter\bin`
|
||||
|
||||
2. **Git for Windows**
|
||||
- Download from: https://git-scm.com/downloads/win
|
||||
|
||||
3. **Code Editor**
|
||||
- Recommended: Visual Studio Code with Flutter extension
|
||||
- Alternative: Android Studio
|
||||
|
||||
### Platform-Specific Requirements
|
||||
|
||||
#### For Android Development
|
||||
|
||||
1. **Android Studio**
|
||||
- Download from: https://developer.android.com/studio
|
||||
- Install Android SDK
|
||||
- Install Android SDK Build-Tools
|
||||
- Install Android Emulator
|
||||
|
||||
2. **Java JDK 11+**
|
||||
- Download from: https://www.oracle.com/java/technologies/downloads/
|
||||
|
||||
#### For iOS Development (macOS only)
|
||||
|
||||
1. **Xcode 14+**
|
||||
- Download from Mac App Store
|
||||
- Install Xcode Command Line Tools
|
||||
|
||||
2. **CocoaPods**
|
||||
```bash
|
||||
sudo gem install cocoapods
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Verify Flutter Installation
|
||||
|
||||
```bash
|
||||
flutter doctor
|
||||
```
|
||||
|
||||
Expected output should show checkmarks for:
|
||||
- Flutter (Channel stable)
|
||||
- Android toolchain
|
||||
- Chrome (for web development)
|
||||
- Visual Studio Code
|
||||
- Connected device
|
||||
|
||||
### 2. Clone the Repository
|
||||
|
||||
```bash
|
||||
cd C:\DEV\COPILOT
|
||||
git clone <repository-url> geutebruck_app
|
||||
cd geutebruck_app
|
||||
```
|
||||
|
||||
### 3. Install Dependencies
|
||||
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
### 4. Generate Code
|
||||
|
||||
The app uses code generation for models, BLoCs, and dependency injection:
|
||||
|
||||
```bash
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
For continuous code generation during development:
|
||||
|
||||
```bash
|
||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
### 5. Configure API Endpoint
|
||||
|
||||
Edit the API configuration file:
|
||||
|
||||
**File:** `lib/core/constants/api_constants.dart`
|
||||
|
||||
```dart
|
||||
class ApiConstants {
|
||||
static const String baseUrl = 'http://localhost:8000'; // Change to your API URL
|
||||
static const Duration timeout = Duration(seconds: 30);
|
||||
}
|
||||
```
|
||||
|
||||
## Running the App
|
||||
|
||||
### On Android Emulator
|
||||
|
||||
1. Start Android emulator:
|
||||
```bash
|
||||
flutter emulators --launch <emulator_id>
|
||||
```
|
||||
|
||||
2. Run the app:
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
### On iOS Simulator (macOS only)
|
||||
|
||||
1. Start iOS simulator:
|
||||
```bash
|
||||
open -a Simulator
|
||||
```
|
||||
|
||||
2. Run the app:
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
### On Physical Device
|
||||
|
||||
1. Enable USB debugging on your device (Android)
|
||||
- Settings → About Phone → Tap Build Number 7 times
|
||||
- Settings → Developer Options → Enable USB Debugging
|
||||
|
||||
2. Connect device via USB
|
||||
|
||||
3. Verify device is detected:
|
||||
```bash
|
||||
flutter devices
|
||||
```
|
||||
|
||||
4. Run the app:
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
### Hot Reload During Development
|
||||
|
||||
While the app is running:
|
||||
- Press `r` to hot reload
|
||||
- Press `R` to hot restart
|
||||
- Press `q` to quit
|
||||
|
||||
## Development Workflow
|
||||
|
||||
### 1. Feature Development
|
||||
|
||||
Follow this workflow for each feature:
|
||||
|
||||
1. **Write Tests First (TDD)**
|
||||
```bash
|
||||
# Create test file
|
||||
test/domain/use_cases/servers/get_servers_test.dart
|
||||
|
||||
# Run test (will fail)
|
||||
flutter test test/domain/use_cases/servers/get_servers_test.dart
|
||||
|
||||
# Implement feature
|
||||
lib/domain/use_cases/servers/get_servers.dart
|
||||
|
||||
# Run test (should pass)
|
||||
flutter test test/domain/use_cases/servers/get_servers_test.dart
|
||||
```
|
||||
|
||||
2. **Generate Code**
|
||||
```bash
|
||||
flutter pub run build_runner build
|
||||
```
|
||||
|
||||
3. **Run App**
|
||||
```bash
|
||||
flutter run
|
||||
```
|
||||
|
||||
### 2. Code Generation
|
||||
|
||||
The app uses several code generators:
|
||||
|
||||
#### Freezed (Immutable Models)
|
||||
|
||||
```dart
|
||||
// Define model
|
||||
@freezed
|
||||
class Server with _$Server {
|
||||
const factory Server({
|
||||
required String id,
|
||||
required String alias,
|
||||
}) = _Server;
|
||||
|
||||
factory Server.fromJson(Map<String, dynamic> json) =>
|
||||
_$ServerFromJson(json);
|
||||
}
|
||||
|
||||
// Generate with:
|
||||
flutter pub run build_runner build
|
||||
```
|
||||
|
||||
#### Injectable (Dependency Injection)
|
||||
|
||||
```dart
|
||||
// Annotate class
|
||||
@injectable
|
||||
class ServerRepository {
|
||||
final ServerRemoteDataSource remoteDataSource;
|
||||
|
||||
ServerRepository(this.remoteDataSource);
|
||||
}
|
||||
|
||||
// Register in injection.dart:
|
||||
@InjectableInit()
|
||||
void configureDependencies() => getIt.init();
|
||||
|
||||
// Generate with:
|
||||
flutter pub run build_runner build
|
||||
```
|
||||
|
||||
### 3. Testing
|
||||
|
||||
#### Run All Tests
|
||||
|
||||
```bash
|
||||
flutter test
|
||||
```
|
||||
|
||||
#### Run Specific Test File
|
||||
|
||||
```bash
|
||||
flutter test test/domain/use_cases/servers/get_servers_test.dart
|
||||
```
|
||||
|
||||
#### Run Tests with Coverage
|
||||
|
||||
```bash
|
||||
flutter test --coverage
|
||||
```
|
||||
|
||||
View coverage report:
|
||||
```bash
|
||||
genhtml coverage/lcov.info -o coverage/html
|
||||
open coverage/html/index.html
|
||||
```
|
||||
|
||||
#### Widget Tests
|
||||
|
||||
```dart
|
||||
testWidgets('ServerListScreen displays servers', (tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(home: ServerListScreen()),
|
||||
);
|
||||
|
||||
expect(find.text('Servers'), findsOneWidget);
|
||||
});
|
||||
```
|
||||
|
||||
#### Integration Tests
|
||||
|
||||
```bash
|
||||
flutter test integration_test/app_test.dart
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
lib/
|
||||
├── core/ # Core utilities and configurations
|
||||
│ ├── constants/
|
||||
│ ├── errors/
|
||||
│ ├── network/
|
||||
│ └── theme/
|
||||
├── data/ # Data layer
|
||||
│ ├── models/ # JSON serializable models
|
||||
│ ├── repositories/ # Repository implementations
|
||||
│ └── data_sources/ # Remote and local data sources
|
||||
├── domain/ # Domain layer
|
||||
│ ├── entities/ # Business entities
|
||||
│ ├── repositories/ # Repository interfaces
|
||||
│ └── use_cases/ # Business logic
|
||||
├── presentation/ # Presentation layer
|
||||
│ ├── blocs/ # BLoC state management
|
||||
│ ├── screens/ # Full-page screens
|
||||
│ └── widgets/ # Reusable widgets
|
||||
├── injection.dart # Dependency injection setup
|
||||
└── main.dart # App entry point
|
||||
```
|
||||
|
||||
## Common Commands
|
||||
|
||||
### Development
|
||||
|
||||
```bash
|
||||
# Run app in debug mode
|
||||
flutter run
|
||||
|
||||
# Run app in profile mode (for performance testing)
|
||||
flutter run --profile
|
||||
|
||||
# Run app in release mode
|
||||
flutter run --release
|
||||
|
||||
# Clean build artifacts
|
||||
flutter clean
|
||||
|
||||
# Update dependencies
|
||||
flutter pub upgrade
|
||||
|
||||
# Check for outdated packages
|
||||
flutter pub outdated
|
||||
|
||||
# Analyze code
|
||||
flutter analyze
|
||||
```
|
||||
|
||||
### Building
|
||||
|
||||
```bash
|
||||
# Build Android APK
|
||||
flutter build apk --release
|
||||
|
||||
# Build Android App Bundle (for Play Store)
|
||||
flutter build appbundle --release
|
||||
|
||||
# Build iOS (macOS only)
|
||||
flutter build ipa --release
|
||||
```
|
||||
|
||||
### Debugging
|
||||
|
||||
```bash
|
||||
# Run with DevTools
|
||||
flutter run --devtools
|
||||
|
||||
# Attach debugger to running app
|
||||
flutter attach
|
||||
|
||||
# Get device logs
|
||||
flutter logs
|
||||
```
|
||||
|
||||
## Environment Configuration
|
||||
|
||||
### Development Environment
|
||||
|
||||
**File:** `lib/core/config/env_config.dart`
|
||||
|
||||
```dart
|
||||
enum Environment { development, staging, production }
|
||||
|
||||
class EnvConfig {
|
||||
static Environment currentEnv = Environment.development;
|
||||
|
||||
static String get apiBaseUrl {
|
||||
switch (currentEnv) {
|
||||
case Environment.development:
|
||||
return 'http://localhost:8000';
|
||||
case Environment.staging:
|
||||
return 'https://staging-api.geutebruck.com';
|
||||
case Environment.production:
|
||||
return 'https://api.geutebruck.com';
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Switch environments:
|
||||
|
||||
```dart
|
||||
// In main.dart
|
||||
void main() {
|
||||
EnvConfig.currentEnv = Environment.production;
|
||||
runApp(MyApp());
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Flutter Doctor Issues
|
||||
|
||||
```bash
|
||||
flutter doctor -v
|
||||
```
|
||||
|
||||
Common fixes:
|
||||
- **Android license not accepted**: `flutter doctor --android-licenses`
|
||||
- **Xcode not configured**: `sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer`
|
||||
|
||||
### Build Runner Issues
|
||||
|
||||
```bash
|
||||
# Clean and rebuild
|
||||
flutter clean
|
||||
flutter pub get
|
||||
flutter pub run build_runner clean
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
### Dependency Conflicts
|
||||
|
||||
```bash
|
||||
# Clear pub cache
|
||||
flutter pub cache repair
|
||||
|
||||
# Clean and reinstall
|
||||
flutter clean
|
||||
rm pubspec.lock
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
### Hot Reload Not Working
|
||||
|
||||
- Try hot restart (press `R`)
|
||||
- Check for syntax errors
|
||||
- Some changes require full restart (native code, assets)
|
||||
|
||||
### Emulator Performance
|
||||
|
||||
For better Android emulator performance:
|
||||
1. Enable hardware acceleration (Intel HAXM or AMD Hypervisor)
|
||||
2. Allocate more RAM to emulator (4GB+)
|
||||
3. Use x86/x64 system images (not ARM)
|
||||
|
||||
## IDE Setup
|
||||
|
||||
### Visual Studio Code
|
||||
|
||||
Install extensions:
|
||||
1. Flutter
|
||||
2. Dart
|
||||
3. Flutter Intl (for internationalization)
|
||||
4. Error Lens
|
||||
5. GitLens
|
||||
|
||||
**Settings (.vscode/settings.json):**
|
||||
|
||||
```json
|
||||
{
|
||||
"dart.lineLength": 120,
|
||||
"editor.formatOnSave": true,
|
||||
"dart.debugExternalPackageLibraries": false,
|
||||
"dart.debugSdkLibraries": false,
|
||||
"[dart]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnType": true,
|
||||
"editor.rulers": [120],
|
||||
"editor.selectionHighlight": false,
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||
"editor.suggestSelection": "first",
|
||||
"editor.tabCompletion": "onlySnippets",
|
||||
"editor.wordBasedSuggestions": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Android Studio
|
||||
|
||||
Install plugins:
|
||||
1. Flutter
|
||||
2. Dart
|
||||
|
||||
Configure:
|
||||
- File → Settings → Languages & Frameworks → Flutter
|
||||
- Set Flutter SDK path
|
||||
|
||||
## API Testing
|
||||
|
||||
Before running the app, ensure the backend API is running:
|
||||
|
||||
```bash
|
||||
# Start API server
|
||||
cd C:\DEV\COPILOT\geutebruck-api
|
||||
python -m uvicorn src.api.main:app --host 0.0.0.0 --port 8000
|
||||
|
||||
# Verify API is accessible
|
||||
curl http://localhost:8000/api/v1/health
|
||||
```
|
||||
|
||||
Test authentication:
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username":"admin","password":"admin123"}'
|
||||
```
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
### GitHub Actions
|
||||
|
||||
**File:** `.github/workflows/flutter.yml`
|
||||
|
||||
```yaml
|
||||
name: Flutter CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, develop ]
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: '3.24.0'
|
||||
channel: 'stable'
|
||||
|
||||
- name: Install dependencies
|
||||
run: flutter pub get
|
||||
|
||||
- name: Generate code
|
||||
run: flutter pub run build_runner build --delete-conflicting-outputs
|
||||
|
||||
- name: Analyze
|
||||
run: flutter analyze
|
||||
|
||||
- name: Run tests
|
||||
run: flutter test --coverage
|
||||
|
||||
- name: Upload coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
files: ./coverage/lcov.info
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: test
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
|
||||
- name: Build APK
|
||||
run: flutter build apk --release
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: app-release.apk
|
||||
path: build/app/outputs/flutter-apk/app-release.apk
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Review Specifications**
|
||||
- Read `constitution.md` for coding standards
|
||||
- Review `spec.md` for user stories
|
||||
- Study `plan.md` for architecture
|
||||
|
||||
2. **Start Development**
|
||||
- Begin with Phase 1 tasks in `tasks.md`
|
||||
- Follow TDD approach (tests first)
|
||||
- Use code generation for models and DI
|
||||
|
||||
3. **Join the Team**
|
||||
- Set up development environment
|
||||
- Clone repository
|
||||
- Create feature branch
|
||||
- Start with assigned tasks
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions:
|
||||
- Check Flutter documentation: https://flutter.dev/docs
|
||||
- BLoC documentation: https://bloclibrary.dev
|
||||
- Project-specific questions: See team lead
|
||||
|
||||
---
|
||||
|
||||
**Happy Coding! 🚀**
|
||||
552
geutebruck-api/specs/001-flutter-app/spec.md
Normal file
552
geutebruck-api/specs/001-flutter-app/spec.md
Normal file
@@ -0,0 +1,552 @@
|
||||
# Geutebruck API Flutter App - Functional Specification
|
||||
|
||||
## Overview
|
||||
|
||||
A mobile application for managing Geutebruck video surveillance systems through the REST API. The app provides administrators with full control over server configurations, action mappings, cameras, monitors, and cross-switching operations.
|
||||
|
||||
## Target Users
|
||||
|
||||
- **System Administrators**: Configure and manage Geutebruck servers
|
||||
- **Security Operators**: Monitor and control video surveillance systems
|
||||
- **Technicians**: Set up action mappings and camera configurations
|
||||
|
||||
## User Stories
|
||||
|
||||
### Epic 1: Authentication & Authorization
|
||||
|
||||
#### US-1.1: User Login
|
||||
**As a** system administrator
|
||||
**I want to** log in with my username and password
|
||||
**So that** I can securely access the system
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Login screen with username and password fields
|
||||
- Secure credential storage using flutter_secure_storage
|
||||
- JWT token received and stored on successful authentication
|
||||
- Error message displayed for invalid credentials
|
||||
- "Remember me" option to persist login
|
||||
- Password visibility toggle
|
||||
- Loading indicator during authentication
|
||||
|
||||
**API Endpoint:** `POST /api/v1/auth/login`
|
||||
|
||||
---
|
||||
|
||||
#### US-1.2: Automatic Token Refresh
|
||||
**As a** logged-in user
|
||||
**I want** my session to remain active without re-logging in
|
||||
**So that** I don't lose access during normal usage
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Access token automatically refreshed before expiration
|
||||
- Refresh token used to obtain new access token
|
||||
- User redirected to login if refresh fails
|
||||
- Silent refresh (no UI disruption)
|
||||
|
||||
**API Endpoint:** `POST /api/v1/auth/refresh`
|
||||
|
||||
---
|
||||
|
||||
#### US-1.3: User Logout
|
||||
**As a** logged-in user
|
||||
**I want to** log out of the application
|
||||
**So that** I can secure my session when done
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Logout button in app drawer/menu
|
||||
- All tokens cleared from secure storage
|
||||
- User redirected to login screen
|
||||
- Confirmation dialog before logout
|
||||
|
||||
---
|
||||
|
||||
### Epic 2: Server Management
|
||||
|
||||
#### US-2.1: View All Servers
|
||||
**As a** system administrator
|
||||
**I want to** see a list of all configured servers (G-Core and GeViScope)
|
||||
**So that** I can manage my infrastructure
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Combined list showing both G-Core and GeViScope servers
|
||||
- Display: alias, host, type (G-Core/GeViScope), enabled status
|
||||
- Search/filter by alias or host
|
||||
- Pull-to-refresh to update list
|
||||
- Server count displayed (total, G-Core, GeViScope)
|
||||
- Visual indicator for enabled/disabled servers
|
||||
- Tap to view details
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/servers`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.2: View G-Core Servers
|
||||
**As a** system administrator
|
||||
**I want to** view only G-Core servers
|
||||
**So that** I can focus on G-Core management
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Filtered list showing only G-Core servers
|
||||
- Display: ID, alias, host, user, enabled status
|
||||
- Search and filter capabilities
|
||||
- Sort by ID, alias, or host
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/servers/gcore`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.3: View GeViScope Servers
|
||||
**As a** system administrator
|
||||
**I want to** view only GeViScope servers
|
||||
**So that** I can focus on GeViScope management
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Filtered list showing only GeViScope servers
|
||||
- Display: ID, alias, host, user, enabled status, dialup settings
|
||||
- Search and filter capabilities
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/servers/geviscope`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.4: View Server Details
|
||||
**As a** system administrator
|
||||
**I want to** view detailed information about a specific server
|
||||
**So that** I can review its configuration
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- All server properties displayed
|
||||
- Connection status indicator
|
||||
- Edit button to modify settings
|
||||
- Delete button to remove server
|
||||
- Test connection button
|
||||
|
||||
**API Endpoints:**
|
||||
- `GET /api/v1/configuration/servers/gcore/{id}`
|
||||
- `GET /api/v1/configuration/servers/geviscope/{id}`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.5: Create G-Core Server
|
||||
**As a** system administrator
|
||||
**I want to** add a new G-Core server
|
||||
**So that** I can expand my managed infrastructure
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Form with fields: alias, host, user, password
|
||||
- Optional fields: enabled, deactivate_echo, deactivate_live_check
|
||||
- Input validation (required fields, valid IP/hostname)
|
||||
- Server ID auto-generated
|
||||
- Success/error feedback
|
||||
- Return to server list on success
|
||||
|
||||
**API Endpoint:** `POST /api/v1/configuration/servers/gcore`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.6: Create GeViScope Server
|
||||
**As a** system administrator
|
||||
**I want to** add a new GeViScope server
|
||||
**So that** I can manage GeViScope systems
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Form with standard fields plus dialup settings
|
||||
- All dialup configuration options available
|
||||
- Input validation
|
||||
- Success/error feedback
|
||||
|
||||
**API Endpoint:** `POST /api/v1/configuration/servers/geviscope`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.7: Update Server
|
||||
**As a** system administrator
|
||||
**I want to** modify an existing server's configuration
|
||||
**So that** I can keep settings current
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Pre-populated form with current values
|
||||
- Editable fields (except ID)
|
||||
- Validation before saving
|
||||
- Confirmation dialog for changes
|
||||
- Success/error feedback
|
||||
|
||||
**API Endpoints:**
|
||||
- `PUT /api/v1/configuration/servers/gcore/{id}`
|
||||
- `PUT /api/v1/configuration/servers/geviscope/{id}`
|
||||
|
||||
---
|
||||
|
||||
#### US-2.8: Delete Server
|
||||
**As a** system administrator
|
||||
**I want to** remove a server from the system
|
||||
**So that** I can clean up unused configurations
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Delete button with confirmation dialog
|
||||
- Warning message about permanent deletion
|
||||
- Success feedback
|
||||
- Return to server list
|
||||
- Server removed from list immediately
|
||||
|
||||
**API Endpoints:**
|
||||
- `DELETE /api/v1/configuration/servers/gcore/{id}`
|
||||
- `DELETE /api/v1/configuration/servers/geviscope/{id}`
|
||||
|
||||
---
|
||||
|
||||
### Epic 3: Action Mapping Management
|
||||
|
||||
#### US-3.1: View Action Mappings
|
||||
**As a** system administrator
|
||||
**I want to** see all configured action mappings
|
||||
**So that** I can understand the automation rules
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- List of all action mappings with caption, ID
|
||||
- Display input action parameters
|
||||
- Display output action count
|
||||
- Search by caption
|
||||
- Pull-to-refresh
|
||||
- Tap to view details
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/action-mappings`
|
||||
|
||||
---
|
||||
|
||||
#### US-3.2: View Action Mapping Details
|
||||
**As a** system administrator
|
||||
**I want to** see detailed information about an action mapping
|
||||
**So that** I can understand its configuration
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Display mapping caption and ID
|
||||
- List all input action parameters with values
|
||||
- List all output actions with:
|
||||
- Action name
|
||||
- Caption
|
||||
- Server
|
||||
- Parameters
|
||||
- Edit and delete buttons
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/action-mappings/{id}`
|
||||
|
||||
---
|
||||
|
||||
#### US-3.3: Create Action Mapping
|
||||
**As a** system administrator
|
||||
**I want to** create a new action mapping
|
||||
**So that** I can automate system responses
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Form with mapping caption
|
||||
- Dynamic input parameter builder
|
||||
- Output action builder with:
|
||||
- Action dropdown (GscAction/GCoreAction)
|
||||
- Server selection
|
||||
- Parameter configuration
|
||||
- PTZ head selection for camera actions
|
||||
- Add multiple output actions
|
||||
- Validation of all fields
|
||||
- Success/error feedback
|
||||
|
||||
**API Endpoint:** `POST /api/v1/configuration/action-mappings`
|
||||
|
||||
---
|
||||
|
||||
#### US-3.4: Update Action Mapping
|
||||
**As a** system administrator
|
||||
**I want to** modify an existing action mapping
|
||||
**So that** I can adjust automation rules
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Pre-populated form with current values
|
||||
- Edit caption, input parameters, output actions
|
||||
- Add/remove output actions
|
||||
- Validation
|
||||
- Success/error feedback
|
||||
|
||||
**API Endpoint:** `PUT /api/v1/configuration/action-mappings/{id}`
|
||||
|
||||
---
|
||||
|
||||
#### US-3.5: Delete Action Mapping
|
||||
**As a** system administrator
|
||||
**I want to** remove an action mapping
|
||||
**So that** I can clean up unused automations
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Delete button with confirmation
|
||||
- Warning about permanent deletion
|
||||
- Success feedback
|
||||
- Removed from list immediately
|
||||
|
||||
**API Endpoint:** `DELETE /api/v1/configuration/action-mappings/{id}`
|
||||
|
||||
---
|
||||
|
||||
### Epic 4: Camera Management
|
||||
|
||||
#### US-4.1: View Camera List
|
||||
**As a** security operator
|
||||
**I want to** see all available cameras
|
||||
**So that** I can select cameras for viewing or control
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- List of all cameras with ID and name
|
||||
- Visual indicator for online/offline status
|
||||
- Search by camera name
|
||||
- Filter by status
|
||||
- Pull-to-refresh
|
||||
|
||||
**API Endpoint:** `GET /api/v1/cameras`
|
||||
|
||||
---
|
||||
|
||||
#### US-4.2: View Camera Details
|
||||
**As a** security operator
|
||||
**I want to** see detailed camera information
|
||||
**So that** I can understand its configuration
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Camera ID, name, description
|
||||
- Connection status
|
||||
- Server assignment
|
||||
- PTZ capabilities indicator
|
||||
- Quick action buttons (if PTZ supported)
|
||||
|
||||
**API Endpoint:** `GET /api/v1/cameras/{id}`
|
||||
|
||||
---
|
||||
|
||||
#### US-4.3: Control PTZ Camera
|
||||
**As a** security operator
|
||||
**I want to** control PTZ camera movements
|
||||
**So that** I can direct camera focus
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- PTZ control pad (Pan Left/Right, Tilt Up/Down)
|
||||
- Zoom In/Out buttons
|
||||
- Focus Near/Far buttons
|
||||
- Stop button for all movements
|
||||
- Speed control slider
|
||||
- Preset position selector
|
||||
- Save preset button
|
||||
- Visual feedback during movement
|
||||
|
||||
**API Endpoints:**
|
||||
- Pan: Actions like PanLeft, PanRight, PanStop
|
||||
- Tilt: TiltUp, TiltDown
|
||||
- Zoom: ZoomIn, ZoomOut, ZoomStop
|
||||
- Focus: FocusNear, FocusFar, FocusStop
|
||||
- Presets: PrePosSave, PrePosCall
|
||||
|
||||
---
|
||||
|
||||
### Epic 5: Monitor Management
|
||||
|
||||
#### US-5.1: View Monitor List
|
||||
**As a** security operator
|
||||
**I want to** see all available monitors
|
||||
**So that** I can manage video displays
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- List of monitors with ID and description
|
||||
- Status indicator
|
||||
- Search and filter
|
||||
- Tap to view details
|
||||
|
||||
**API Endpoint:** `GET /api/v1/monitors`
|
||||
|
||||
---
|
||||
|
||||
#### US-5.2: View Monitor Details
|
||||
**As a** security operator
|
||||
**I want to** see monitor configuration details
|
||||
**So that** I can understand its setup
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Monitor ID, description, layout
|
||||
- Current camera assignments
|
||||
- Quick actions (clear, assign camera)
|
||||
|
||||
**API Endpoint:** `GET /api/v1/monitors/{id}`
|
||||
|
||||
---
|
||||
|
||||
### Epic 6: Cross-Switching
|
||||
|
||||
#### US-6.1: Assign Camera to Monitor
|
||||
**As a** security operator
|
||||
**I want to** connect a camera to a monitor
|
||||
**So that** I can view live video
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Camera selector (dropdown or search)
|
||||
- Monitor selector
|
||||
- Preview of current assignments
|
||||
- Connect button
|
||||
- Success/error feedback
|
||||
- Live video preview (optional)
|
||||
|
||||
**API Endpoint:** `POST /api/v1/crossswitch/connect`
|
||||
|
||||
---
|
||||
|
||||
#### US-6.2: Clear Monitor
|
||||
**As a** security operator
|
||||
**I want to** disconnect all cameras from a monitor
|
||||
**So that** I can reset the display
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Monitor selector
|
||||
- Confirmation dialog
|
||||
- Clear button
|
||||
- Success feedback
|
||||
|
||||
**API Endpoint:** `POST /api/v1/crossswitch/clear`
|
||||
|
||||
---
|
||||
|
||||
### Epic 7: Configuration Management
|
||||
|
||||
#### US-7.1: Export Configuration
|
||||
**As a** system administrator
|
||||
**I want to** export the complete system configuration
|
||||
**So that** I can back it up or migrate it
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Export button in settings
|
||||
- JSON format export
|
||||
- Save to device storage
|
||||
- Share option (email, cloud)
|
||||
- Export includes all servers, action mappings, etc.
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/export`
|
||||
|
||||
---
|
||||
|
||||
#### US-7.2: View Configuration Tree
|
||||
**As a** system administrator
|
||||
**I want to** browse the raw configuration structure
|
||||
**So that** I can troubleshoot or verify settings
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Expandable tree view
|
||||
- Search/filter nodes
|
||||
- Display node types and values
|
||||
- Read-only view
|
||||
|
||||
**API Endpoint:** `GET /api/v1/configuration/tree`
|
||||
|
||||
---
|
||||
|
||||
### Epic 8: User Interface & Navigation
|
||||
|
||||
#### US-8.1: App Navigation
|
||||
**As a** user
|
||||
**I want** intuitive navigation between app sections
|
||||
**So that** I can efficiently access features
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Bottom navigation bar with:
|
||||
- Servers
|
||||
- Action Mappings
|
||||
- Cameras
|
||||
- Monitors
|
||||
- Side drawer with:
|
||||
- Configuration
|
||||
- Settings
|
||||
- About
|
||||
- Logout
|
||||
- Back button support
|
||||
- Clear visual hierarchy
|
||||
|
||||
---
|
||||
|
||||
#### US-8.2: Settings Screen
|
||||
**As a** user
|
||||
**I want to** configure app preferences
|
||||
**So that** I can customize my experience
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- API base URL configuration
|
||||
- Theme selection (Light/Dark/System)
|
||||
- Language selection
|
||||
- Notification preferences
|
||||
- Cache management
|
||||
- About section with version info
|
||||
|
||||
---
|
||||
|
||||
#### US-8.3: Error Handling
|
||||
**As a** user
|
||||
**I want** clear error messages and recovery options
|
||||
**So that** I understand what went wrong and how to proceed
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Network error: Retry button, offline indicator
|
||||
- Authentication error: Redirect to login
|
||||
- Validation error: Field-specific messages
|
||||
- Server error: Error details with support contact
|
||||
- Snackbar notifications for temporary messages
|
||||
- Error logging for debugging
|
||||
|
||||
---
|
||||
|
||||
#### US-8.4: Loading States
|
||||
**As a** user
|
||||
**I want** visual feedback during operations
|
||||
**So that** I know the app is working
|
||||
|
||||
**Acceptance Criteria:**
|
||||
- Shimmer loading for lists
|
||||
- Progress indicators for long operations
|
||||
- Pull-to-refresh animation
|
||||
- Button loading state (disabled with spinner)
|
||||
|
||||
---
|
||||
|
||||
## Non-Functional Requirements
|
||||
|
||||
### Performance
|
||||
- App launch time: < 3 seconds on modern devices
|
||||
- List scrolling: 60 FPS
|
||||
- API response time: Visual feedback within 100ms
|
||||
- Image loading: Progressive rendering with placeholders
|
||||
|
||||
### Security
|
||||
- All data transmission over HTTPS
|
||||
- Tokens stored in secure storage
|
||||
- Auto-logout after 30 minutes of inactivity
|
||||
- No sensitive data in logs
|
||||
|
||||
### Compatibility
|
||||
- Android 8.0 (API level 26) and above
|
||||
- iOS 12.0 and above
|
||||
- Support for phones and tablets
|
||||
|
||||
### Accessibility
|
||||
- Screen reader support
|
||||
- Minimum touch target size: 48x48 dp
|
||||
- Contrast ratio: 4.5:1 for text
|
||||
- Semantic labels for all interactive elements
|
||||
|
||||
### Offline Support
|
||||
- Cache server lists, action mappings
|
||||
- Queue operations when offline
|
||||
- Sync when connection restored
|
||||
- Offline indicator in UI
|
||||
|
||||
## Review & Acceptance Checklist
|
||||
|
||||
- [ ] All user stories implemented with acceptance criteria met
|
||||
- [ ] Unit test coverage ≥ 80%
|
||||
- [ ] Widget tests for all screens
|
||||
- [ ] Integration tests for critical flows
|
||||
- [ ] API integration tested against live backend
|
||||
- [ ] Performance metrics validated
|
||||
- [ ] Security review completed
|
||||
- [ ] Accessibility tested with screen reader
|
||||
- [ ] User acceptance testing completed
|
||||
- [ ] Documentation updated
|
||||
811
geutebruck-api/specs/001-flutter-app/tasks.md
Normal file
811
geutebruck-api/specs/001-flutter-app/tasks.md
Normal file
@@ -0,0 +1,811 @@
|
||||
# Geutebruck API Flutter App - Implementation Tasks
|
||||
|
||||
## Implementation Status (Last Updated: 2025-12-23)
|
||||
|
||||
### ✅ Completed Features (Phase 1 & 2)
|
||||
- **US-1.1**: User Login - Login screen with authentication ✅
|
||||
- **US-1.2**: Token Management - Secure storage with flutter_secure_storage ✅
|
||||
- **US-2.1**: View All Servers - Server list with filtering (All/G-Core/GeViScope) ✅
|
||||
- **US-2.5**: Create G-Core Server - Full form implementation ✅
|
||||
- **US-2.6**: Create GeViScope Server - Full form implementation ✅
|
||||
- **US-2.7**: Update Server - Edit functionality with proper state handling ✅
|
||||
- **US-2.8**: Delete Server - Delete with confirmation dialog ✅
|
||||
- **Navigation**: App drawer with left menu navigation ✅
|
||||
- **Offline-First**: Hive local storage with sync capabilities ✅
|
||||
- **Server Sync**: Upload dirty changes to remote server ✅
|
||||
- **Server Download**: Download latest configuration from server ✅
|
||||
- **State Management**: BLoC pattern with shared state across routes ✅
|
||||
|
||||
### 🐛 Recent Bug Fixes
|
||||
- Fixed "No data" display issue after server update (2025-12-23)
|
||||
- Issue: BlocBuilder fallback showing "No data" during state transitions
|
||||
- Solution: Changed fallback to show loading indicator instead
|
||||
- File: `lib/presentation/screens/servers/servers_management_screen.dart:268`
|
||||
|
||||
### 🚧 In Progress
|
||||
- Testing and validation of server management features
|
||||
|
||||
### 📋 Pending (Phase 3-9)
|
||||
- US-3.x: Action Mapping Management
|
||||
- US-4.x: Camera Management
|
||||
- US-5.x: Monitor & Cross-Switching
|
||||
- US-6.x: Cross-Switch Management
|
||||
- US-7.x: Configuration Export/Tree View
|
||||
- US-8.x: Additional UI/UX improvements
|
||||
|
||||
---
|
||||
|
||||
## Task Organization
|
||||
|
||||
Tasks are organized by user story and marked with:
|
||||
- `[P]` - Can be done in parallel
|
||||
- `[✅]` - Completed
|
||||
- `[🚧]` - In Progress
|
||||
- File paths indicate where code should be created/modified
|
||||
- TDD tasks (tests) listed before implementation tasks
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation & Setup
|
||||
|
||||
### Task Group: Project Setup
|
||||
|
||||
#### TASK-001 [P] [✅]: Create Flutter Project
|
||||
**File:** N/A (command line)
|
||||
```bash
|
||||
flutter create geutebruck_app
|
||||
cd geutebruck_app
|
||||
```
|
||||
|
||||
#### TASK-002 [P] [✅]: Configure Dependencies
|
||||
**File:** `pubspec.yaml`
|
||||
- Add all required dependencies from plan.md
|
||||
- Set Flutter SDK constraints
|
||||
- Configure assets folder
|
||||
|
||||
#### TASK-003 [✅]: Setup Folder Structure
|
||||
**Files:** Create folder structure as defined in plan.md
|
||||
```
|
||||
lib/core/
|
||||
lib/data/
|
||||
lib/domain/
|
||||
lib/presentation/
|
||||
```
|
||||
|
||||
#### TASK-004 [P] [✅]: Configure Analysis Options
|
||||
**File:** `analysis_options.yaml`
|
||||
- Add very_good_analysis
|
||||
- Configure lint rules
|
||||
- Enable strict mode
|
||||
|
||||
#### TASK-005 [P] [✅]: Setup Build Configuration
|
||||
**File:** `build.yaml`
|
||||
- Configure freezed
|
||||
- Configure json_serializable
|
||||
- Configure injectable
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-1.1 - User Login
|
||||
|
||||
#### TASK-010: Create Auth Entities (Test)
|
||||
**File:** `test/domain/entities/user_test.dart`
|
||||
- Test User entity creation
|
||||
- Test equality
|
||||
- Test copyWith
|
||||
|
||||
#### TASK-011: Create Auth Entities
|
||||
**File:** `lib/domain/entities/user.dart`
|
||||
```dart
|
||||
@freezed
|
||||
class User with _$User {
|
||||
const factory User({
|
||||
required String id,
|
||||
required String username,
|
||||
required String role,
|
||||
}) = _User;
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-012: Create Auth Models (Test)
|
||||
**File:** `test/data/models/auth_model_test.dart`
|
||||
- Test JSON deserialization
|
||||
- Test toEntity conversion
|
||||
|
||||
#### TASK-013: Create Auth Models
|
||||
**File:** `lib/data/models/auth_model.dart`
|
||||
```dart
|
||||
@freezed
|
||||
class AuthResponse with _$AuthResponse {
|
||||
factory AuthResponse({
|
||||
required String accessToken,
|
||||
required String refreshToken,
|
||||
required UserModel user,
|
||||
}) = _AuthResponse;
|
||||
|
||||
factory AuthResponse.fromJson(Map<String, dynamic> json) =>
|
||||
_$AuthResponseFromJson(json);
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-014: Create Secure Storage Manager (Test)
|
||||
**File:** `test/data/data_sources/local/secure_storage_manager_test.dart`
|
||||
- Test token storage
|
||||
- Test token retrieval
|
||||
- Test token deletion
|
||||
|
||||
#### TASK-015: Create Secure Storage Manager
|
||||
**File:** `lib/data/data_sources/local/secure_storage_manager.dart`
|
||||
```dart
|
||||
@injectable
|
||||
class SecureStorageManager {
|
||||
final FlutterSecureStorage _storage;
|
||||
|
||||
Future<void> saveToken(String key, String token);
|
||||
Future<String?> getToken(String key);
|
||||
Future<void> deleteToken(String key);
|
||||
Future<void> clearAll();
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-016: Create Auth Remote Data Source (Test)
|
||||
**File:** `test/data/data_sources/remote/auth_remote_data_source_test.dart`
|
||||
- Mock Dio client
|
||||
- Test login API call
|
||||
- Test error handling
|
||||
|
||||
#### TASK-017: Create Auth Remote Data Source
|
||||
**File:** `lib/data/data_sources/remote/auth_remote_data_source.dart`
|
||||
```dart
|
||||
@injectable
|
||||
class AuthRemoteDataSource {
|
||||
final Dio _dio;
|
||||
|
||||
Future<AuthResponse> login(String username, String password);
|
||||
Future<AuthResponse> refreshToken(String refreshToken);
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-018: Create Auth Repository (Test)
|
||||
**File:** `test/data/repositories/auth_repository_impl_test.dart`
|
||||
- Mock data sources
|
||||
- Test login flow
|
||||
- Test token storage
|
||||
|
||||
#### TASK-019: Create Auth Repository
|
||||
**File:** `lib/data/repositories/auth_repository_impl.dart`
|
||||
- Implement repository interface
|
||||
- Coordinate data sources
|
||||
- Handle errors with Either<Failure, T>
|
||||
|
||||
#### TASK-020: Create Login Use Case (Test)
|
||||
**File:** `test/domain/use_cases/auth/login_test.dart`
|
||||
- Mock repository
|
||||
- Test successful login
|
||||
- Test failed login
|
||||
|
||||
#### TASK-021: Create Login Use Case
|
||||
**File:** `lib/domain/use_cases/auth/login.dart`
|
||||
```dart
|
||||
@injectable
|
||||
class Login {
|
||||
final AuthRepository repository;
|
||||
|
||||
Future<Either<Failure, User>> call(String username, String password);
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-022: Create Auth BLoC (Test)
|
||||
**File:** `test/presentation/blocs/auth/auth_bloc_test.dart`
|
||||
- Use bloc_test package
|
||||
- Test all events and state transitions
|
||||
- Mock use cases
|
||||
|
||||
#### TASK-023: Create Auth BLoC
|
||||
**File:** `lib/presentation/blocs/auth/auth_bloc.dart`
|
||||
```dart
|
||||
@injectable
|
||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
final Login login;
|
||||
final RefreshToken refreshToken;
|
||||
final Logout logout;
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-024: Create Login Screen (Widget Test)
|
||||
**File:** `test/presentation/screens/auth/login_screen_test.dart`
|
||||
- Test UI rendering
|
||||
- Test form validation
|
||||
- Test login button tap
|
||||
|
||||
#### TASK-025: Create Login Screen
|
||||
**File:** `lib/presentation/screens/auth/login_screen.dart`
|
||||
- Username and password fields
|
||||
- Login button
|
||||
- Loading state
|
||||
- Error display
|
||||
- BLoC integration
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-1.2 - Automatic Token Refresh
|
||||
|
||||
#### TASK-030: Create Auth Interceptor (Test)
|
||||
**File:** `test/core/network/interceptors/auth_interceptor_test.dart`
|
||||
- Test token injection
|
||||
- Test 401 handling
|
||||
- Test token refresh flow
|
||||
|
||||
#### TASK-031: Create Auth Interceptor
|
||||
**File:** `lib/core/network/interceptors/auth_interceptor.dart`
|
||||
```dart
|
||||
class AuthInterceptor extends Interceptor {
|
||||
@override
|
||||
void onRequest(RequestOptions, RequestInterceptorHandler);
|
||||
|
||||
@override
|
||||
void onError(DioException, ErrorInterceptorHandler);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Server Management
|
||||
|
||||
### Task Group: US-2.1 - View All Servers
|
||||
|
||||
#### TASK-040: Create Server Entities
|
||||
**Files:**
|
||||
- `lib/domain/entities/server.dart`
|
||||
- `lib/domain/entities/gcore_server.dart`
|
||||
- `lib/domain/entities/geviscope_server.dart`
|
||||
|
||||
#### TASK-041: Create Server Models
|
||||
**Files:**
|
||||
- `lib/data/models/server_model.dart`
|
||||
- Include JSON serialization
|
||||
|
||||
#### TASK-042: Create Server Remote Data Source
|
||||
**File:** `lib/data/data_sources/remote/server_remote_data_source.dart`
|
||||
```dart
|
||||
@RestApi(baseUrl: '/api/v1/configuration')
|
||||
abstract class ServerRemoteDataSource {
|
||||
factory ServerRemoteDataSource(Dio dio) = _ServerRemoteDataSource;
|
||||
|
||||
@GET('/servers')
|
||||
Future<ServerListResponse> getServers();
|
||||
|
||||
@GET('/servers/gcore')
|
||||
Future<GCoreServerListResponse> getGCoreServers();
|
||||
|
||||
@GET('/servers/geviscope')
|
||||
Future<GeViScopeServerListResponse> getGeViScopeServers();
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-043: Create Cache Manager
|
||||
**File:** `lib/data/data_sources/local/cache_manager.dart`
|
||||
- Implement Hive boxes
|
||||
- Cache servers with expiration
|
||||
- Cache action mappings
|
||||
|
||||
#### TASK-044: Create Server Repository
|
||||
**File:** `lib/data/repositories/server_repository_impl.dart`
|
||||
- Implement all server operations
|
||||
- Cache-first strategy
|
||||
- Error handling
|
||||
|
||||
#### TASK-045: Create Get Servers Use Case
|
||||
**File:** `lib/domain/use_cases/servers/get_servers.dart`
|
||||
|
||||
#### TASK-046: Create Server BLoC
|
||||
**File:** `lib/presentation/blocs/server/server_bloc.dart`
|
||||
- Events: LoadServers, CreateServer, UpdateServer, DeleteServer
|
||||
- States: Initial, Loading, Loaded, Error
|
||||
|
||||
#### TASK-047: Create Server List Screen
|
||||
**File:** `lib/presentation/screens/servers/server_list_screen.dart`
|
||||
- AppBar with title and actions
|
||||
- ListView with ServerCard widgets
|
||||
- Pull-to-refresh
|
||||
- Search functionality
|
||||
- Filter chips (All, G-Core, GeViScope)
|
||||
- FAB for adding new server
|
||||
|
||||
#### TASK-048: Create Server Card Widget
|
||||
**File:** `lib/presentation/widgets/server/server_card.dart`
|
||||
- Display server alias, host, type
|
||||
- Status indicator (enabled/disabled)
|
||||
- Tap to view details
|
||||
- Swipe actions (edit, delete)
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-2.4 - View Server Details
|
||||
|
||||
#### TASK-050: Create Server Detail Screen
|
||||
**File:** `lib/presentation/screens/servers/server_detail_screen.dart`
|
||||
- Display all server properties
|
||||
- Edit and Delete buttons
|
||||
- Connection status indicator
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-2.5/2.6 - Create Server
|
||||
|
||||
#### TASK-055: Create Server Form Screen
|
||||
**File:** `lib/presentation/screens/servers/server_form_screen.dart`
|
||||
- Use flutter_form_builder
|
||||
- Dynamic form based on server type
|
||||
- Validation
|
||||
- Submit button with loading state
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-2.7 - Update Server
|
||||
|
||||
#### TASK-060: Create Update Server Use Case
|
||||
**File:** `lib/domain/use_cases/servers/update_server.dart`
|
||||
|
||||
#### TASK-061: Update Server Form Screen
|
||||
**File:** Same as TASK-055
|
||||
- Pre-populate form with existing values
|
||||
- Update mode vs create mode
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-2.8 - Delete Server
|
||||
|
||||
#### TASK-065: Create Delete Server Use Case
|
||||
**File:** `lib/domain/use_cases/servers/delete_server.dart`
|
||||
|
||||
#### TASK-066: Add Delete Confirmation Dialog
|
||||
**File:** `lib/presentation/widgets/common/confirmation_dialog.dart`
|
||||
- Reusable confirmation dialog
|
||||
- Customizable title and message
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Action Mapping Management
|
||||
|
||||
### Task Group: US-3.1/3.2 - View Action Mappings
|
||||
|
||||
#### TASK-070: Create Action Mapping Entities
|
||||
**File:** `lib/domain/entities/action_mapping.dart`
|
||||
```dart
|
||||
@freezed
|
||||
class ActionMapping with _$ActionMapping {
|
||||
const factory ActionMapping({
|
||||
required int id,
|
||||
required String caption,
|
||||
required Map<String, String> inputActions,
|
||||
required List<OutputAction> outputActions,
|
||||
}) = _ActionMapping;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class OutputAction with _$OutputAction {
|
||||
const factory OutputAction({
|
||||
required String action,
|
||||
required String caption,
|
||||
String? server,
|
||||
required Map<String, String> parameters,
|
||||
}) = _OutputAction;
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-071: Create Action Mapping Models
|
||||
**File:** `lib/data/models/action_mapping_model.dart`
|
||||
|
||||
#### TASK-072: Create Action Mapping Remote Data Source
|
||||
**File:** `lib/data/data_sources/remote/action_mapping_remote_data_source.dart`
|
||||
```dart
|
||||
@RestApi(baseUrl: '/api/v1/configuration')
|
||||
abstract class ActionMappingRemoteDataSource {
|
||||
@GET('/action-mappings')
|
||||
Future<List<ActionMappingModel>> getActionMappings();
|
||||
|
||||
@GET('/action-mappings/{id}')
|
||||
Future<ActionMappingModel> getActionMapping(@Path() int id);
|
||||
|
||||
@POST('/action-mappings')
|
||||
Future<void> createActionMapping(@Body() ActionMappingCreateRequest request);
|
||||
|
||||
@PUT('/action-mappings/{id}')
|
||||
Future<void> updateActionMapping(
|
||||
@Path() int id,
|
||||
@Body() ActionMappingUpdateRequest request,
|
||||
);
|
||||
|
||||
@DELETE('/action-mappings/{id}')
|
||||
Future<void> deleteActionMapping(@Path() int id);
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-073: Create Action Mapping Repository
|
||||
**File:** `lib/data/repositories/action_mapping_repository_impl.dart`
|
||||
|
||||
#### TASK-074: Create Action Mapping Use Cases
|
||||
**Files:**
|
||||
- `lib/domain/use_cases/action_mappings/get_action_mappings.dart`
|
||||
- `lib/domain/use_cases/action_mappings/create_action_mapping.dart`
|
||||
- `lib/domain/use_cases/action_mappings/update_action_mapping.dart`
|
||||
- `lib/domain/use_cases/action_mappings/delete_action_mapping.dart`
|
||||
|
||||
#### TASK-075: Create Action Mapping BLoC
|
||||
**File:** `lib/presentation/blocs/action_mapping/action_mapping_bloc.dart`
|
||||
|
||||
#### TASK-076: Create Action Mapping List Screen
|
||||
**File:** `lib/presentation/screens/action_mappings/action_mapping_list_screen.dart`
|
||||
|
||||
#### TASK-077: Create Action Mapping Detail Screen
|
||||
**File:** `lib/presentation/screens/action_mappings/action_mapping_detail_screen.dart`
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-3.3/3.4 - Create/Update Action Mapping
|
||||
|
||||
#### TASK-080: Create Action Mapping Form Screen
|
||||
**File:** `lib/presentation/screens/action_mappings/action_mapping_form_screen.dart`
|
||||
- Caption field
|
||||
- Input parameter builder
|
||||
- Add/remove parameters
|
||||
- Key-value pairs
|
||||
- Output action builder
|
||||
- Action type selector
|
||||
- Server selector
|
||||
- Parameter configuration
|
||||
- Add/remove actions
|
||||
- Submit button
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Camera Management
|
||||
|
||||
### Task Group: US-4.1/4.2 - Camera List and Details
|
||||
|
||||
#### TASK-090: Create Camera Entities
|
||||
**File:** `lib/domain/entities/camera.dart`
|
||||
|
||||
#### TASK-091: Create Camera Models
|
||||
**File:** `lib/data/models/camera_model.dart`
|
||||
|
||||
#### TASK-092: Create Camera Remote Data Source
|
||||
**File:** `lib/data/data_sources/remote/camera_remote_data_source.dart`
|
||||
```dart
|
||||
@RestApi(baseUrl: '/api/v1/cameras')
|
||||
abstract class CameraRemoteDataSource {
|
||||
@GET('')
|
||||
Future<List<CameraModel>> getCameras();
|
||||
|
||||
@GET('/{id}')
|
||||
Future<CameraModel> getCamera(@Path() String id);
|
||||
}
|
||||
```
|
||||
|
||||
#### TASK-093: Create Camera Repository
|
||||
**File:** `lib/data/repositories/camera_repository_impl.dart`
|
||||
|
||||
#### TASK-094: Create Camera Use Cases
|
||||
**Files:**
|
||||
- `lib/domain/use_cases/cameras/get_cameras.dart`
|
||||
- `lib/domain/use_cases/cameras/get_camera.dart`
|
||||
|
||||
#### TASK-095: Create Camera BLoC
|
||||
**File:** `lib/presentation/blocs/camera/camera_bloc.dart`
|
||||
|
||||
#### TASK-096: Create Camera List Screen
|
||||
**File:** `lib/presentation/screens/cameras/camera_list_screen.dart`
|
||||
|
||||
#### TASK-097: Create Camera Detail Screen
|
||||
**File:** `lib/presentation/screens/cameras/camera_detail_screen.dart`
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-4.3 - PTZ Camera Control
|
||||
|
||||
#### TASK-100: Create PTZ Control Use Cases
|
||||
**Files:**
|
||||
- `lib/domain/use_cases/cameras/control_ptz.dart`
|
||||
- Support all PTZ actions (pan, tilt, zoom, focus)
|
||||
|
||||
#### TASK-101: Create PTZ BLoC
|
||||
**File:** `lib/presentation/blocs/ptz/ptz_bloc.dart`
|
||||
|
||||
#### TASK-102: Create Camera Control Screen
|
||||
**File:** `lib/presentation/screens/cameras/camera_control_screen.dart`
|
||||
- PTZ control pad widget
|
||||
- Directional buttons (up, down, left, right)
|
||||
- Zoom controls (+/-)
|
||||
- Focus controls (near/far)
|
||||
- Stop button
|
||||
- Speed slider
|
||||
- Preset selector
|
||||
- Save preset button
|
||||
|
||||
#### TASK-103: Create PTZ Control Pad Widget
|
||||
**File:** `lib/presentation/widgets/camera/ptz_control_pad.dart`
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Monitor & Cross-Switching
|
||||
|
||||
### Task Group: US-5.1/5.2 - Monitor Management
|
||||
|
||||
#### TASK-110: Create Monitor Entities
|
||||
**File:** `lib/domain/entities/monitor.dart`
|
||||
|
||||
#### TASK-111: Create Monitor Models
|
||||
**File:** `lib/data/models/monitor_model.dart`
|
||||
|
||||
#### TASK-112: Create Monitor Remote Data Source
|
||||
**File:** `lib/data/data_sources/remote/monitor_remote_data_source.dart`
|
||||
|
||||
#### TASK-113: Create Monitor Repository
|
||||
**File:** `lib/data/repositories/monitor_repository_impl.dart`
|
||||
|
||||
#### TASK-114: Create Monitor Use Cases
|
||||
**Files:**
|
||||
- `lib/domain/use_cases/monitors/get_monitors.dart`
|
||||
- `lib/domain/use_cases/monitors/get_monitor.dart`
|
||||
|
||||
#### TASK-115: Create Monitor BLoC
|
||||
**File:** `lib/presentation/blocs/monitor/monitor_bloc.dart`
|
||||
|
||||
#### TASK-116: Create Monitor List Screen
|
||||
**File:** `lib/presentation/screens/monitors/monitor_list_screen.dart`
|
||||
|
||||
#### TASK-117: Create Monitor Detail Screen
|
||||
**File:** `lib/presentation/screens/monitors/monitor_detail_screen.dart`
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-6.1/6.2 - Cross-Switching
|
||||
|
||||
#### TASK-120: Create Cross-Switch Use Cases
|
||||
**Files:**
|
||||
- `lib/domain/use_cases/crossswitch/connect_camera_to_monitor.dart`
|
||||
- `lib/domain/use_cases/crossswitch/clear_monitor.dart`
|
||||
|
||||
#### TASK-121: Create Cross-Switch BLoC
|
||||
**File:** `lib/presentation/blocs/crossswitch/crossswitch_bloc.dart`
|
||||
|
||||
#### TASK-122: Create Cross-Switch Screen
|
||||
**File:** `lib/presentation/screens/crossswitch/crossswitch_screen.dart`
|
||||
- Camera selector
|
||||
- Monitor selector
|
||||
- Preview of current assignments
|
||||
- Connect button
|
||||
- Clear button
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Configuration Management
|
||||
|
||||
### Task Group: US-7.1 - Export Configuration
|
||||
|
||||
#### TASK-130: Create Export Configuration Use Case
|
||||
**File:** `lib/domain/use_cases/configuration/export_configuration.dart`
|
||||
|
||||
#### TASK-131: Add Export to Settings Screen
|
||||
**File:** `lib/presentation/screens/settings/settings_screen.dart`
|
||||
- Export button
|
||||
- Save to file dialog
|
||||
- Share option
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-7.2 - View Configuration Tree
|
||||
|
||||
#### TASK-135: Create Configuration Tree Screen
|
||||
**File:** `lib/presentation/screens/configuration/configuration_tree_screen.dart`
|
||||
- Expandable tree view
|
||||
- Search functionality
|
||||
- Node type indicators
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: UI & Navigation
|
||||
|
||||
### Task Group: US-8.1 - App Navigation
|
||||
|
||||
#### TASK-140: Setup GoRouter
|
||||
**File:** `lib/core/router/app_router.dart`
|
||||
```dart
|
||||
final router = GoRouter(
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '/login',
|
||||
builder: (context, state) => LoginScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/servers',
|
||||
builder: (context, state) => ServerListScreen(),
|
||||
),
|
||||
// ... other routes
|
||||
],
|
||||
);
|
||||
```
|
||||
|
||||
#### TASK-141: Create App Shell with Bottom Navigation
|
||||
**File:** `lib/presentation/screens/app_shell.dart`
|
||||
- Bottom navigation bar
|
||||
- Side drawer
|
||||
- Route management
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-8.2 - Settings Screen
|
||||
|
||||
#### TASK-145: Create Settings Screen
|
||||
**File:** `lib/presentation/screens/settings/settings_screen.dart`
|
||||
- API base URL configuration
|
||||
- Theme selector
|
||||
- Language selector
|
||||
- Cache management
|
||||
- About section
|
||||
|
||||
---
|
||||
|
||||
### Task Group: US-8.3/8.4 - Error Handling & Loading States
|
||||
|
||||
#### TASK-150: Create Common Widgets
|
||||
**Files:**
|
||||
- `lib/presentation/widgets/common/loading_widget.dart`
|
||||
- Shimmer loading for lists
|
||||
- Circular progress for buttons
|
||||
- `lib/presentation/widgets/common/error_widget.dart`
|
||||
- Error icon and message
|
||||
- Retry button
|
||||
- `lib/presentation/widgets/common/empty_state_widget.dart`
|
||||
- Empty list message
|
||||
- Illustration
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: Testing & Polish
|
||||
|
||||
### Task Group: Comprehensive Testing
|
||||
|
||||
#### TASK-160 [P]: Write Unit Tests for All Use Cases
|
||||
**Files:** `test/domain/use_cases/**/*_test.dart`
|
||||
- Achieve 80%+ coverage
|
||||
|
||||
#### TASK-161 [P]: Write Widget Tests for All Screens
|
||||
**Files:** `test/presentation/screens/**/*_test.dart`
|
||||
|
||||
#### TASK-162 [P]: Write Integration Tests
|
||||
**Files:** `integration_test/app_test.dart`
|
||||
- Login flow
|
||||
- Server CRUD
|
||||
- Action mapping CRUD
|
||||
|
||||
---
|
||||
|
||||
### Task Group: Performance Optimization
|
||||
|
||||
#### TASK-170: Implement List Pagination
|
||||
**Files:** Update all list screens
|
||||
- Infinite scroll
|
||||
- Page size: 20 items
|
||||
|
||||
#### TASK-171: Optimize Image Loading
|
||||
**Files:** Update image widgets
|
||||
- Use cached_network_image
|
||||
- Progressive loading
|
||||
|
||||
#### TASK-172: Implement Request Debouncing
|
||||
**Files:** Update search fields
|
||||
- Debounce duration: 300ms
|
||||
|
||||
---
|
||||
|
||||
### Task Group: Accessibility
|
||||
|
||||
#### TASK-175: Add Semantic Labels
|
||||
**Files:** All widgets
|
||||
- Proper semantic labels for screen readers
|
||||
|
||||
#### TASK-176: Test with Screen Reader
|
||||
**Files:** N/A (manual testing)
|
||||
|
||||
#### TASK-177: Verify Contrast Ratios
|
||||
**Files:** `lib/core/theme/colors.dart`
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Deployment Preparation
|
||||
|
||||
### Task Group: App Configuration
|
||||
|
||||
#### TASK-180: Configure App Icons
|
||||
**File:** Run flutter_launcher_icons
|
||||
|
||||
#### TASK-181: Configure Splash Screen
|
||||
**File:** Run flutter_native_splash
|
||||
|
||||
#### TASK-182: Update App Metadata
|
||||
**Files:**
|
||||
- `android/app/src/main/AndroidManifest.xml`
|
||||
- `ios/Runner/Info.plist`
|
||||
|
||||
---
|
||||
|
||||
### Task Group: Build & Release
|
||||
|
||||
#### TASK-185: Create Release Build (Android)
|
||||
```bash
|
||||
flutter build apk --release
|
||||
flutter build appbundle --release
|
||||
```
|
||||
|
||||
#### TASK-186: Create Release Build (iOS)
|
||||
```bash
|
||||
flutter build ipa --release
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies Between Tasks
|
||||
|
||||
```
|
||||
Foundation Tasks (001-005) → All other tasks
|
||||
|
||||
Authentication:
|
||||
010-011 → 012-013 → 014-015 → 016-017 → 018-019 → 020-021 → 022-023 → 024-025
|
||||
030-031 (depends on 022-023)
|
||||
|
||||
Servers:
|
||||
040-041 → 042-043 → 044 → 045 → 046 → 047-048
|
||||
050 (depends on 046)
|
||||
055 (depends on 046)
|
||||
060-061 (depends on 046)
|
||||
065-066 (depends on 046)
|
||||
|
||||
Action Mappings:
|
||||
070-071 → 072 → 073 → 074 → 075 → 076-077
|
||||
080 (depends on 075)
|
||||
|
||||
Cameras:
|
||||
090-091 → 092 → 093 → 094 → 095 → 096-097
|
||||
100-103 (depends on 095)
|
||||
|
||||
Monitors:
|
||||
110-111 → 112 → 113 → 114 → 115 → 116-117
|
||||
|
||||
Cross-Switching:
|
||||
120-122 (depends on 095 and 115)
|
||||
|
||||
Configuration:
|
||||
130-131
|
||||
135
|
||||
|
||||
Navigation:
|
||||
140-141 (depends on all screens being created)
|
||||
|
||||
Settings:
|
||||
145
|
||||
|
||||
Common Widgets:
|
||||
150 (can be done in parallel, used by many screens)
|
||||
|
||||
Testing:
|
||||
160-162 (depends on all implementations)
|
||||
|
||||
Performance:
|
||||
170-172 (depends on screens)
|
||||
|
||||
Accessibility:
|
||||
175-177 (depends on all widgets)
|
||||
|
||||
Deployment:
|
||||
180-186 (depends on everything)
|
||||
```
|
||||
|
||||
## Parallel Execution Opportunities
|
||||
|
||||
Tasks marked with `[P]` can be executed in parallel:
|
||||
- TASK-001, 002, 004, 005 (setup tasks)
|
||||
- TASK-160, 161, 162 (testing can be distributed)
|
||||
|
||||
Multiple developers can work on different epics simultaneously once foundation is complete.
|
||||
1396
geutebruck-api/specs/001-surveillance-api/contracts/openapi.yaml
Normal file
1396
geutebruck-api/specs/001-surveillance-api/contracts/openapi.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1188
geutebruck-api/specs/001-surveillance-api/data-model.md
Normal file
1188
geutebruck-api/specs/001-surveillance-api/data-model.md
Normal file
File diff suppressed because it is too large
Load Diff
572
geutebruck-api/specs/001-surveillance-api/plan.md
Normal file
572
geutebruck-api/specs/001-surveillance-api/plan.md
Normal file
@@ -0,0 +1,572 @@
|
||||
# Implementation Plan: Geutebruck Surveillance API
|
||||
|
||||
**Branch**: `001-surveillance-api` | **Date**: 2025-12-08 | **Spec**: [spec.md](./spec.md)
|
||||
**Input**: Feature specification from `/specs/001-surveillance-api/spec.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Build a production-ready REST API for Geutebruck GeViScope/GeViSoft video surveillance systems, enabling developers to integrate surveillance capabilities into custom applications without direct SDK complexity. The system uses a C# gRPC bridge to interface with the GeViScope SDK, exposing clean REST/WebSocket endpoints through Python FastAPI.
|
||||
|
||||
**Technical Approach**: Python FastAPI + C# gRPC SDK Bridge + GeViScope SDK → delivers <200ms API responses, supports 100+ concurrent video streams, and handles 1000+ WebSocket event subscribers.
|
||||
|
||||
## Geutebruck System Architecture
|
||||
|
||||
**IMPORTANT**: Understanding the Geutebruck architecture is critical for correct implementation:
|
||||
|
||||
### GeViSoft (GeViServer.exe) - Central Matrix Server
|
||||
- **Role**: Video matrix/central management server
|
||||
- **Purpose**: Manages and routes video between multiple GeViScope servers
|
||||
- **Does NOT**: Have cameras or monitors directly connected
|
||||
- **Connects to**: Multiple GeViScope servers (configured as G-Core servers)
|
||||
- **Location**: Typically runs on central management machine
|
||||
- **Configuration**: TestMKS.set contains G-Core server connections
|
||||
|
||||
### GeViScope (GSCServer.exe) - Storage/Recording Servers
|
||||
- **Role**: Video recording and storage servers
|
||||
- **Purpose**: Record video, manage local cameras and monitors
|
||||
- **Has**: IP cameras and video monitors directly connected
|
||||
- **Multiple instances**: You can have many GeViScope servers
|
||||
- **Location**: Typically runs on-site at camera locations
|
||||
- **Configuration**: Each has its own camera/monitor setup
|
||||
|
||||
### System Hierarchy
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ GeViSoft (GeViServer.exe) │
|
||||
│ - Central video matrix │
|
||||
│ - Routes video between GeViScope servers │
|
||||
│ - NO cameras directly attached │
|
||||
│ │
|
||||
│ Connects to G-Core Servers (configured in │
|
||||
│ TestMKS.set GeViGCoreServer folder): │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ GeViScope Server 1 (GSCServer.exe) │ │
|
||||
│ │ Host: 192.168.1.100 │ │
|
||||
│ │ ├─ IP Camera 1 │ │
|
||||
│ │ ├─ IP Camera 2 │ │
|
||||
│ │ ├─ IP Camera 3 │ │
|
||||
│ │ └─ Monitor 1 │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ GeViScope Server 2 (GSCServer.exe) │ │
|
||||
│ │ Host: 192.168.1.200 │ │
|
||||
│ │ ├─ IP Camera 4 │ │
|
||||
│ │ ├─ IP Camera 5 │ │
|
||||
│ │ └─ Monitor 2 │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ GeViScope Server 3 (localhost) │ │
|
||||
│ │ Host: localhost OR 127.0.0.1 │ │
|
||||
│ │ ├─ IP Camera 6 │ │
|
||||
│ │ ├─ IP Camera 7 │ │
|
||||
│ │ └─ Monitor 3 │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### API Data Flow
|
||||
```
|
||||
REST API Request (GET /cameras)
|
||||
↓
|
||||
SDK Bridge (gRPC)
|
||||
↓
|
||||
GeViScope SDK (GeViProcAPINET_4_0.dll)
|
||||
↓
|
||||
GeViSoft (GeViServer.exe) - Central matrix
|
||||
↓ Queries all connected G-Core servers
|
||||
├──> GeViScope Server 1 → Returns cameras 1-3
|
||||
├──> GeViScope Server 2 → Returns cameras 4-5
|
||||
└──> GeViScope Server 3 → Returns cameras 6-7
|
||||
↓
|
||||
Combined camera list returned to API
|
||||
```
|
||||
|
||||
### G-Core Server Configuration
|
||||
The **GeViGCoreServer** entries in TestMKS.set are connection definitions telling GeViSoft which GeViScope servers to connect to:
|
||||
|
||||
```
|
||||
TestMKS.set/
|
||||
GeViGCoreServer/
|
||||
Server_1/ ← Connection to GeViScope at 192.168.1.100
|
||||
Alias: "Office Building"
|
||||
Host: "192.168.1.100"
|
||||
Enabled: true
|
||||
Server_2/ ← Connection to GeViScope at 192.168.1.200
|
||||
Alias: "Warehouse"
|
||||
Host: "192.168.1.200"
|
||||
Enabled: true
|
||||
Server_localhost/ ← Connection to LOCAL GeViScope
|
||||
Alias: "Local Storage"
|
||||
Host: "localhost"
|
||||
Enabled: true
|
||||
```
|
||||
|
||||
**Critical**: For cameras to appear in the API, GeViSoft must successfully connect to at least one GeViScope server that has cameras configured.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: Python 3.11+, C# .NET Framework 4.8 (SDK bridge), C# .NET 8.0 (gRPC service)
|
||||
**Primary Dependencies**:
|
||||
- **Python**: FastAPI, Uvicorn, SQLAlchemy, Redis (aioredis), protobuf, grpcio, PyJWT, asyncio
|
||||
- **C#**: GeViScope SDK (GeViProcAPINET_4_0.dll), Grpc.Core, Google.Protobuf
|
||||
**Storage**: PostgreSQL 14+ (user management, session storage, audit logs), Redis 6.0+ (session cache, pub/sub for WebSocket events)
|
||||
**Testing**: pytest (Python), xUnit (.NET), 80% minimum coverage, TDD enforced
|
||||
**Target Platform**: Windows Server 2016+ (SDK bridge + GeViServer), Linux (FastAPI server - optional)
|
||||
**Project Type**: Web (backend API + SDK bridge service)
|
||||
**Performance Goals**:
|
||||
- <200ms p95 for metadata queries (camera lists, status)
|
||||
- <2s stream initialization
|
||||
- <100ms event notification delivery
|
||||
- 100+ concurrent video streams
|
||||
- 1000+ concurrent WebSocket connections
|
||||
**Constraints**:
|
||||
- SDK requires Windows x86 (32-bit) runtime
|
||||
- Visual C++ 2010 Redistributable (x86) mandatory
|
||||
- Full GeViSoft installation required (not just SDK)
|
||||
- GeViServer must be running on network-accessible host
|
||||
- All SDK operations must use Channel-based architecture
|
||||
**Scale/Scope**:
|
||||
- Support 50+ cameras per installation
|
||||
- Handle 10k+ events/hour during peak activity
|
||||
- Store 90 days audit logs (configurable)
|
||||
- Support 100+ concurrent operators
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
### Constitution Alignment
|
||||
|
||||
✅ **Single Source of Truth**: OpenAPI spec serves as the contract, auto-generated from code
|
||||
✅ **Test-First Development**: TDD enforced with pytest/xUnit, 80% minimum coverage
|
||||
✅ **Simplicity**: REST over custom protocols, JWT over session cookies, direct stream URLs over proxying
|
||||
✅ **Clear Abstractions**: SDK Bridge isolates SDK complexity from Python API layer
|
||||
✅ **Error Handling**: SDK errors translated to HTTP status codes with user-friendly messages
|
||||
✅ **Documentation**: Auto-generated OpenAPI docs at `/docs`, quickstart guide provided
|
||||
✅ **Security First**: JWT authentication, RBAC, rate limiting, audit logging, TLS enforcement
|
||||
|
||||
### Exceptions to Constitution
|
||||
|
||||
None. All design decisions align with constitution principles.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/001-surveillance-api/
|
||||
├── plan.md # This file (implementation plan)
|
||||
├── spec.md # Feature specification (user stories, requirements)
|
||||
├── research.md # Phase 0 output (technical research, architectural decisions)
|
||||
├── data-model.md # Phase 1 output (entity schemas, relationships, validation)
|
||||
├── quickstart.md # Phase 1 output (developer quick start guide)
|
||||
├── contracts/ # Phase 1 output (API contracts)
|
||||
│ └── openapi.yaml # Complete OpenAPI 3.0 specification
|
||||
└── tasks.md # Phase 2 output (will be generated by /speckit.tasks)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```text
|
||||
geutebruck-api/
|
||||
├── src/
|
||||
│ ├── api/ # Python FastAPI application
|
||||
│ │ ├── main.py # FastAPI app entry point
|
||||
│ │ ├── config.py # Configuration management (env vars)
|
||||
│ │ ├── models/ # SQLAlchemy ORM models
|
||||
│ │ │ ├── user.py
|
||||
│ │ │ ├── camera.py
|
||||
│ │ │ ├── event.py
|
||||
│ │ │ └── audit_log.py
|
||||
│ │ ├── schemas/ # Pydantic request/response models
|
||||
│ │ │ ├── auth.py
|
||||
│ │ │ ├── camera.py
|
||||
│ │ │ ├── stream.py
|
||||
│ │ │ ├── event.py
|
||||
│ │ │ └── recording.py
|
||||
│ │ ├── routers/ # FastAPI route handlers
|
||||
│ │ │ ├── auth.py # /api/v1/auth/*
|
||||
│ │ │ ├── cameras.py # /api/v1/cameras/*
|
||||
│ │ │ ├── events.py # /api/v1/events/*
|
||||
│ │ │ ├── recordings.py # /api/v1/recordings/*
|
||||
│ │ │ ├── analytics.py # /api/v1/analytics/*
|
||||
│ │ │ └── system.py # /api/v1/health, /status
|
||||
│ │ ├── services/ # Business logic layer
|
||||
│ │ │ ├── auth_service.py
|
||||
│ │ │ ├── camera_service.py
|
||||
│ │ │ ├── stream_service.py
|
||||
│ │ │ ├── event_service.py
|
||||
│ │ │ └── recording_service.py
|
||||
│ │ ├── clients/ # External service clients
|
||||
│ │ │ ├── sdk_bridge_client.py # gRPC client for SDK bridge
|
||||
│ │ │ └── redis_client.py # Redis connection pooling
|
||||
│ │ ├── middleware/ # FastAPI middleware
|
||||
│ │ │ ├── auth_middleware.py
|
||||
│ │ │ ├── rate_limiter.py
|
||||
│ │ │ └── error_handler.py
|
||||
│ │ ├── websocket/ # WebSocket event streaming
|
||||
│ │ │ ├── connection_manager.py
|
||||
│ │ │ └── event_broadcaster.py
|
||||
│ │ ├── utils/ # Utility functions
|
||||
│ │ │ ├── jwt_utils.py
|
||||
│ │ │ └── error_translation.py
|
||||
│ │ └── migrations/ # Alembic database migrations
|
||||
│ │ └── versions/
|
||||
│ │
|
||||
│ └── sdk-bridge/ # C# gRPC service (SDK wrapper)
|
||||
│ ├── GeViScopeBridge.sln
|
||||
│ ├── GeViScopeBridge/
|
||||
│ │ ├── Program.cs # gRPC server entry point
|
||||
│ │ ├── Services/
|
||||
│ │ │ ├── CameraService.cs # Camera operations
|
||||
│ │ │ ├── StreamService.cs # Stream management
|
||||
│ │ │ ├── EventService.cs # Event subscriptions
|
||||
│ │ │ ├── RecordingService.cs # Recording management
|
||||
│ │ │ └── AnalyticsService.cs # Analytics configuration
|
||||
│ │ ├── SDK/
|
||||
│ │ │ ├── GeViDatabaseWrapper.cs
|
||||
│ │ │ ├── StateQueryHandler.cs
|
||||
│ │ │ ├── DatabaseQueryHandler.cs
|
||||
│ │ │ └── ActionDispatcher.cs
|
||||
│ │ ├── Models/ # Internal data models
|
||||
│ │ └── Utils/
|
||||
│ └── Protos/ # gRPC protocol definitions
|
||||
│ ├── camera.proto
|
||||
│ ├── stream.proto
|
||||
│ ├── event.proto
|
||||
│ ├── recording.proto
|
||||
│ └── analytics.proto
|
||||
│
|
||||
├── tests/
|
||||
│ ├── api/
|
||||
│ │ ├── unit/ # Unit tests for Python services
|
||||
│ │ │ ├── test_auth_service.py
|
||||
│ │ │ ├── test_camera_service.py
|
||||
│ │ │ └── test_event_service.py
|
||||
│ │ ├── integration/ # Integration tests with SDK bridge
|
||||
│ │ │ ├── test_camera_operations.py
|
||||
│ │ │ ├── test_stream_lifecycle.py
|
||||
│ │ │ └── test_event_notifications.py
|
||||
│ │ └── contract/ # OpenAPI contract validation
|
||||
│ │ └── test_openapi_compliance.py
|
||||
│ │
|
||||
│ └── sdk-bridge/
|
||||
│ ├── Unit/ # C# unit tests
|
||||
│ │ ├── CameraServiceTests.cs
|
||||
│ │ └── StateQueryTests.cs
|
||||
│ └── Integration/ # Tests with actual SDK
|
||||
│ └── SdkIntegrationTests.cs
|
||||
│
|
||||
├── docs/
|
||||
│ ├── architecture.md # System architecture diagram
|
||||
│ ├── sdk-integration.md # SDK integration patterns
|
||||
│ └── deployment.md # Production deployment guide
|
||||
│
|
||||
├── scripts/
|
||||
│ ├── setup_dev_environment.ps1 # Development environment setup
|
||||
│ ├── start_services.ps1 # Start all services (Redis, SDK Bridge, API)
|
||||
│ └── run_tests.sh # Test execution script
|
||||
│
|
||||
├── .env.example # Environment variable template
|
||||
├── requirements.txt # Python dependencies
|
||||
├── pyproject.toml # Python project configuration
|
||||
├── alembic.ini # Database migration configuration
|
||||
└── README.md # Project overview
|
||||
```
|
||||
|
||||
**Structure Decision**: Web application structure selected (backend API + SDK bridge service) because:
|
||||
1. SDK requires Windows runtime → isolated C# bridge service
|
||||
2. API layer can run on Linux → flexibility for deployment
|
||||
3. Clear separation between SDK complexity and API logic
|
||||
4. gRPC provides high-performance, typed communication between layers
|
||||
5. Python layer handles web concerns (HTTP, WebSocket, auth, validation)
|
||||
|
||||
## Phase 0 - Research ✅ COMPLETED
|
||||
|
||||
**Deliverable**: [research.md](./research.md)
|
||||
|
||||
**Key Decisions**:
|
||||
1. **SDK Integration Method**: C# gRPC bridge service (not pythonnet, subprocess, or COM)
|
||||
- Rationale: Isolates SDK crashes, maintains type safety, enables independent scaling
|
||||
2. **Stream Architecture**: Direct RTSP URLs with token authentication (not API proxy)
|
||||
- Rationale: Reduces API latency, leverages existing streaming infrastructure
|
||||
3. **Event Distribution**: FastAPI WebSocket + Redis Pub/Sub
|
||||
- Rationale: Supports 1000+ concurrent connections, horizontal scaling capability
|
||||
4. **Authentication**: JWT with Redis session storage
|
||||
- Rationale: Stateless validation, flexible permissions, Redis for quick invalidation
|
||||
5. **Performance Strategy**: Async Python + gRPC connection pooling
|
||||
- Rationale: Non-blocking I/O for concurrent operations, <200ms response targets
|
||||
|
||||
**Critical Discoveries**:
|
||||
- Visual C++ 2010 Redistributable (x86) mandatory for SDK DLL loading
|
||||
- Full GeViSoft installation required (not just SDK)
|
||||
- Windows Forms context needed for mixed-mode C++/CLI assemblies
|
||||
- GeViServer ports: 7700, 7701, 7703 (NOT 7707 as initially assumed)
|
||||
- SDK connection pattern: Create → RegisterCallback → Connect (order matters!)
|
||||
- State Queries use GetFirst/GetNext iteration for enumerating entities
|
||||
|
||||
See [SDK_INTEGRATION_LESSONS.md](../../SDK_INTEGRATION_LESSONS.md) for complete details.
|
||||
|
||||
## Phase 1 - Design ✅ COMPLETED
|
||||
|
||||
**Deliverables**:
|
||||
- [data-model.md](./data-model.md) - Entity schemas, relationships, validation rules
|
||||
- [contracts/openapi.yaml](./contracts/openapi.yaml) - Complete REST API specification
|
||||
- [quickstart.md](./quickstart.md) - Developer quick start guide
|
||||
|
||||
**Key Components**:
|
||||
|
||||
### Data Model
|
||||
- **User**: Authentication, RBAC (viewer/operator/administrator), permissions
|
||||
- **Camera**: Channel-based, capabilities (PTZ, analytics), status tracking
|
||||
- **Stream**: Active sessions with token-authenticated URLs
|
||||
- **Event**: Surveillance occurrences (motion, alarms, analytics)
|
||||
- **Recording**: Video segments with ring buffer management
|
||||
- **AnalyticsConfig**: VMD, NPR, OBTRACK configuration per camera
|
||||
|
||||
### API Endpoints (RESTful)
|
||||
- `POST /api/v1/auth/login` - Authenticate and get JWT tokens
|
||||
- `POST /api/v1/auth/refresh` - Refresh access token
|
||||
- `POST /api/v1/auth/logout` - Invalidate tokens
|
||||
- `GET /api/v1/cameras` - List cameras with filtering
|
||||
- `GET /api/v1/cameras/{id}` - Get camera details
|
||||
- `POST /api/v1/cameras/{id}/stream` - Start video stream
|
||||
- `DELETE /api/v1/cameras/{id}/stream/{stream_id}` - Stop stream
|
||||
- `POST /api/v1/cameras/{id}/ptz` - PTZ control commands
|
||||
- `WS /api/v1/events/stream` - WebSocket event notifications
|
||||
- `GET /api/v1/events` - Query event history
|
||||
- `GET /api/v1/recordings` - Query recordings
|
||||
- `POST /api/v1/recordings/{id}/export` - Export video segment
|
||||
- `GET /api/v1/analytics/{camera_id}` - Get analytics configuration
|
||||
- `POST /api/v1/analytics/{camera_id}` - Configure analytics
|
||||
- `GET /api/v1/health` - System health check
|
||||
- `GET /api/v1/status` - Detailed system status
|
||||
|
||||
### gRPC Service Definitions
|
||||
- **CameraService**: ListCameras, GetCameraDetails, GetCameraStatus
|
||||
- **StreamService**: StartStream, StopStream, GetStreamStatus
|
||||
- **PTZService**: MoveCamera, SetPreset, GotoPreset
|
||||
- **EventService**: SubscribeEvents, UnsubscribeEvents (server streaming)
|
||||
- **RecordingService**: QueryRecordings, StartRecording, StopRecording
|
||||
- **AnalyticsService**: ConfigureAnalytics, GetAnalyticsConfig
|
||||
|
||||
## Phase 2 - Configuration Management ✅ COMPLETED (2025-12-16)
|
||||
|
||||
**Implemented**: GeViSoft configuration management via REST API and gRPC SDK Bridge
|
||||
|
||||
**Deliverables**:
|
||||
- G-Core Server CRUD operations (CREATE, READ, DELETE working; UPDATE has known bug)
|
||||
- Action Mapping CRUD operations (CREATE, READ, UPDATE, DELETE all working)
|
||||
- SetupClient integration for configuration download/upload
|
||||
- Configuration tree parsing and navigation
|
||||
- Critical bug fixes (cascade deletion prevention)
|
||||
|
||||
**Key Components Implemented**:
|
||||
|
||||
### REST API Endpoints
|
||||
- `GET /api/v1/configuration/servers` - List all G-Core servers
|
||||
- `GET /api/v1/configuration/servers/{server_id}` - Get single server
|
||||
- `POST /api/v1/configuration/servers` - Create new server
|
||||
- `PUT /api/v1/configuration/servers/{server_id}` - Update server (⚠️ known bug)
|
||||
- `DELETE /api/v1/configuration/servers/{server_id}` - Delete server
|
||||
- `GET /api/v1/configuration/action-mappings` - List all action mappings
|
||||
- `GET /api/v1/configuration/action-mappings/{mapping_id}` - Get single mapping
|
||||
- `POST /api/v1/configuration/action-mappings` - Create mapping
|
||||
- `PUT /api/v1/configuration/action-mappings/{mapping_id}` - Update mapping
|
||||
- `DELETE /api/v1/configuration/action-mappings/{mapping_id}` - Delete mapping
|
||||
|
||||
### gRPC SDK Bridge Implementation
|
||||
- **ConfigurationService**: Complete CRUD operations for servers and action mappings
|
||||
- **SetupClient Integration**: Download/upload .set configuration files
|
||||
- **FolderTreeParser**: Parse GeViSoft binary configuration format
|
||||
- **FolderTreeWriter**: Write configuration changes back to GeViSoft
|
||||
|
||||
### Critical Fixes
|
||||
- **Cascade Deletion Bug** (2025-12-16): Fixed critical bug where deleting multiple action mappings in ascending order caused ID shifting, resulting in deletion of wrong mappings
|
||||
- **Solution**: Always delete in reverse order (highest ID first)
|
||||
- **Impact**: Prevented data loss of ~54 mappings during testing
|
||||
- **Documentation**: CRITICAL_BUG_FIX_DELETE.md
|
||||
|
||||
### Test Scripts
|
||||
- `comprehensive_crud_test.py` - Full CRUD verification with server and mapping operations
|
||||
- `safe_delete_test.py` - Minimal test to verify cascade deletion fix
|
||||
- `server_manager.py` - Production-ready server lifecycle management
|
||||
- `cleanup_to_base.py` - Restore configuration to base state
|
||||
- `verify_config_via_grpc.py` - Configuration verification tool
|
||||
|
||||
### Known Issues
|
||||
- Server UPDATE operation fails with "Server ID is required" error (documented, workaround: delete and recreate)
|
||||
- Bool fields stored as int32 in GeViSoft configuration (acceptable - GeViSet reads correctly)
|
||||
|
||||
**Documentation**:
|
||||
- [SERVER_CRUD_IMPLEMENTATION.md](../../SERVER_CRUD_IMPLEMENTATION.md) - Complete implementation guide
|
||||
- [CRITICAL_BUG_FIX_DELETE.md](../../CRITICAL_BUG_FIX_DELETE.md) - Cascade deletion bug analysis
|
||||
|
||||
**Next**: Phase 3 - Implement remaining user stories (streams, events, analytics)
|
||||
|
||||
## Phase 3 - Tasks ⏭️ NEXT
|
||||
|
||||
**Command**: `/speckit.tasks`
|
||||
|
||||
Will generate:
|
||||
- Task breakdown with dependencies
|
||||
- Implementation order (TDD-first)
|
||||
- Test plan for each task
|
||||
- Acceptance criteria per task
|
||||
- Time estimates
|
||||
|
||||
**Expected Task Categories**:
|
||||
1. **Infrastructure Setup**: Repository structure, development environment, CI/CD
|
||||
2. **SDK Bridge Foundation**: gRPC server, SDK wrapper, basic camera queries
|
||||
3. **API Foundation**: FastAPI app, authentication, middleware
|
||||
4. **Core Features**: Camera management, stream lifecycle, event notifications
|
||||
5. **Extended Features**: Recording management, analytics configuration
|
||||
6. **Testing & Documentation**: Contract tests, integration tests, deployment docs
|
||||
|
||||
## Phase 4 - Implementation ⏭️ FUTURE
|
||||
|
||||
**Command**: `/speckit.implement`
|
||||
|
||||
Will execute TDD implementation:
|
||||
- Red: Write failing test
|
||||
- Green: Minimal code to pass test
|
||||
- Refactor: Clean up while maintaining passing tests
|
||||
- Repeat for each task
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
No constitution violations. All design decisions follow simplicity and clarity principles:
|
||||
- ✅ REST over custom protocols
|
||||
- ✅ JWT over session management
|
||||
- ✅ Direct streaming over proxying
|
||||
- ✅ Clear layer separation (API ↔ Bridge ↔ SDK)
|
||||
- ✅ Standard patterns (FastAPI, gRPC, SQLAlchemy)
|
||||
|
||||
## Technology Stack Summary
|
||||
|
||||
### Python API Layer
|
||||
- **Web Framework**: FastAPI 0.104+
|
||||
- **ASGI Server**: Uvicorn with uvloop
|
||||
- **ORM**: SQLAlchemy 2.0+
|
||||
- **Database**: PostgreSQL 14+
|
||||
- **Cache/PubSub**: Redis 6.0+ (aioredis)
|
||||
- **Authentication**: PyJWT, passlib (bcrypt)
|
||||
- **gRPC Client**: grpcio, protobuf
|
||||
- **Validation**: Pydantic v2
|
||||
- **Testing**: pytest, pytest-asyncio, httpx
|
||||
- **Code Quality**: ruff (linting), black (formatting), mypy (type checking)
|
||||
|
||||
### C# SDK Bridge
|
||||
- **Framework**: .NET Framework 4.8 (SDK runtime), .NET 8.0 (gRPC service)
|
||||
- **gRPC**: Grpc.Core, Grpc.Tools
|
||||
- **SDK**: GeViScope SDK 7.9.975.68+ (GeViProcAPINET_4_0.dll)
|
||||
- **Testing**: xUnit, Moq
|
||||
- **Logging**: Serilog
|
||||
|
||||
### Infrastructure
|
||||
- **Database**: PostgreSQL 14+ (user data, audit logs)
|
||||
- **Cache**: Redis 6.0+ (sessions, pub/sub)
|
||||
- **Deployment**: Docker (API layer), Windows Service (SDK bridge)
|
||||
- **CI/CD**: GitHub Actions
|
||||
- **Monitoring**: Prometheus metrics, Grafana dashboards
|
||||
|
||||
## Commands Reference
|
||||
|
||||
### Development
|
||||
```bash
|
||||
# Setup environment
|
||||
.\scripts\setup_dev_environment.ps1
|
||||
|
||||
# Start all services
|
||||
.\scripts\start_services.ps1
|
||||
|
||||
# Run API server (development)
|
||||
cd src/api
|
||||
uvicorn main:app --reload --host 0.0.0.0 --port 8000
|
||||
|
||||
# Run SDK bridge (development)
|
||||
cd src/sdk-bridge
|
||||
dotnet run --configuration Debug
|
||||
|
||||
# Run tests
|
||||
pytest tests/api -v --cov=src/api --cov-report=html # Python
|
||||
dotnet test tests/sdk-bridge/ # C#
|
||||
|
||||
# Format code
|
||||
ruff check src/api --fix # Python linting
|
||||
black src/api # Python formatting
|
||||
|
||||
# Database migrations
|
||||
alembic upgrade head # Apply migrations
|
||||
alembic revision --autogenerate -m "description" # Create migration
|
||||
```
|
||||
|
||||
### API Usage
|
||||
```bash
|
||||
# Authenticate
|
||||
curl -X POST http://localhost:8000/api/v1/auth/login \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"username": "sysadmin", "password": "masterkey"}'
|
||||
|
||||
# List cameras
|
||||
curl -X GET http://localhost:8000/api/v1/cameras \
|
||||
-H "Authorization: Bearer YOUR_TOKEN"
|
||||
|
||||
# Start stream
|
||||
curl -X POST http://localhost:8000/api/v1/cameras/{id}/stream \
|
||||
-H "Authorization: Bearer YOUR_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"resolution": {"width": 1920, "height": 1080, "fps": 30}, "format": "h264"}'
|
||||
|
||||
# WebSocket events (Python)
|
||||
import websockets
|
||||
uri = f"ws://localhost:8000/api/v1/events/stream?token={TOKEN}"
|
||||
async with websockets.connect(uri) as ws:
|
||||
await ws.send('{"action": "subscribe", "filters": {"event_types": ["motion_detected"]}}')
|
||||
while True:
|
||||
event = await ws.recv()
|
||||
print(event)
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Run `/speckit.tasks`** to generate Phase 2 task breakdown
|
||||
2. **Review tasks** for sequencing and dependencies
|
||||
3. **Execute `/speckit.implement`** to begin TDD implementation
|
||||
4. **Iterate** through tasks following Red-Green-Refactor cycle
|
||||
|
||||
## References
|
||||
|
||||
### Project Documentation
|
||||
- **Specification**: [spec.md](./spec.md) - User stories, requirements, success criteria
|
||||
- **Research**: [research.md](./research.md) - Technical decisions and architectural analysis
|
||||
- **Data Model**: [data-model.md](./data-model.md) - Entity schemas and relationships
|
||||
- **API Contract**: [contracts/openapi.yaml](./contracts/openapi.yaml) - Complete REST API spec
|
||||
- **Quick Start**: [quickstart.md](./quickstart.md) - Developer onboarding guide
|
||||
- **SDK Lessons**: [../../SDK_INTEGRATION_LESSONS.md](../../SDK_INTEGRATION_LESSONS.md) - Critical SDK integration knowledge
|
||||
- **Constitution**: [../../.specify/memory/constitution.md](../../.specify/memory/constitution.md) - Development principles
|
||||
|
||||
### SDK Documentation (Extracted & Searchable)
|
||||
**Location**: `C:\Gevisoft\Documentation\extracted_html\`
|
||||
|
||||
- **Comprehensive SDK Reference**: `C:\DEV\COPILOT\gevisoft-sdk-reference.md`
|
||||
- Complete guide to GeViSoft .NET SDK
|
||||
- Action mapping implementation patterns
|
||||
- Code examples and best practices
|
||||
- Generated: 2025-12-11
|
||||
|
||||
**Key Documentation Files**:
|
||||
- **Action Mapping**: `GeViSoft_SDK_Documentation\313Action Mapping.htm`
|
||||
- **State Queries**: `GeViSoft_SDK_Documentation\414StateQueries.htm`
|
||||
- **Database Queries**: `GeViSoft_SDK_Documentation\415DatabaseQueries.htm`
|
||||
- **GeViAPIClient Reference**: `GeViSoft_API_Documentation\class_ge_vi_a_p_i_client.html`
|
||||
- **CAction Reference**: `GeViSoft_API_Documentation\class_ge_vi_a_p_i___namespace_1_1_c_action.html`
|
||||
|
||||
---
|
||||
|
||||
**Plan Status**: Phase 0 ✅ | Phase 1 ✅ | Phase 2 ⏭️ | Phase 3 🔄 IN PROGRESS (Configuration Management ✅)
|
||||
**Last Updated**: 2025-12-16
|
||||
700
geutebruck-api/specs/001-surveillance-api/quickstart.md
Normal file
700
geutebruck-api/specs/001-surveillance-api/quickstart.md
Normal file
@@ -0,0 +1,700 @@
|
||||
# Quick Start Guide
|
||||
|
||||
**Geutebruck Surveillance API** - REST API for GeViScope/GeViSoft video surveillance systems
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This API provides RESTful access to Geutebruck surveillance systems, enabling:
|
||||
|
||||
- **Camera Management**: List cameras, get status, control PTZ
|
||||
- **Live Streaming**: Start/stop video streams with token authentication
|
||||
- **Event Monitoring**: Subscribe to real-time surveillance events (motion, alarms, analytics)
|
||||
- **Recording Access**: Query and export recorded video segments
|
||||
- **Analytics Configuration**: Configure video analytics (VMD, NPR, object tracking)
|
||||
|
||||
**Architecture**: Python FastAPI + C# gRPC SDK Bridge + GeViScope SDK
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### System Requirements
|
||||
|
||||
- **Operating System**: Windows 10/11 or Windows Server 2016+
|
||||
- **GeViSoft Installation**: Full GeViSoft application + SDK
|
||||
- **Visual C++ 2010 Redistributable (x86)**: Required for SDK
|
||||
- **Python**: 3.11+ (for API server)
|
||||
- **.NET Framework**: 4.8 (for SDK bridge)
|
||||
- **Redis**: 6.0+ (for session management and pub/sub)
|
||||
|
||||
### GeViSoft SDK Setup
|
||||
|
||||
**CRITICAL**: Install in this exact order:
|
||||
|
||||
1. **Install Visual C++ 2010 Redistributable (x86)**
|
||||
```powershell
|
||||
# Download and install
|
||||
Invoke-WebRequest -Uri 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe' -OutFile 'vcredist_x86_2010.exe'
|
||||
Start-Process -FilePath 'vcredist_x86_2010.exe' -ArgumentList '/install', '/quiet', '/norestart' -Wait
|
||||
```
|
||||
|
||||
2. **Install GeViSoft Full Application**
|
||||
- Download from Geutebruck
|
||||
- Run installer
|
||||
- Complete setup wizard
|
||||
|
||||
3. **Install GeViSoft SDK**
|
||||
- Download SDK installer
|
||||
- Run SDK setup
|
||||
- Verify installation in `C:\Program Files (x86)\GeViScopeSDK\`
|
||||
|
||||
4. **Start GeViServer**
|
||||
```cmd
|
||||
cd C:\GEVISOFT
|
||||
GeViServer.exe console
|
||||
```
|
||||
|
||||
**Verification**:
|
||||
```powershell
|
||||
# Check GeViServer is running
|
||||
netstat -an | findstr "7700 7701 7703"
|
||||
# Should show LISTENING on these ports
|
||||
```
|
||||
|
||||
See [SDK_INTEGRATION_LESSONS.md](../../SDK_INTEGRATION_LESSONS.md) for complete deployment details.
|
||||
|
||||
---
|
||||
|
||||
## Installation
|
||||
|
||||
### 1. Clone Repository
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-org/geutebruck-api.git
|
||||
cd geutebruck-api
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
**Python API Server**:
|
||||
```bash
|
||||
cd src/api
|
||||
python -m venv venv
|
||||
venv\Scripts\activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
**C# SDK Bridge**:
|
||||
```bash
|
||||
cd src/sdk-bridge
|
||||
dotnet restore
|
||||
dotnet build --configuration Release
|
||||
```
|
||||
|
||||
### 3. Install Redis
|
||||
|
||||
**Using Chocolatey**:
|
||||
```powershell
|
||||
choco install redis-64
|
||||
redis-server
|
||||
```
|
||||
|
||||
Or download from: https://redis.io/download
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Create `.env` file in `src/api/`:
|
||||
|
||||
```env
|
||||
# API Configuration
|
||||
API_HOST=0.0.0.0
|
||||
API_PORT=8000
|
||||
API_TITLE=Geutebruck Surveillance API
|
||||
API_VERSION=1.0.0
|
||||
|
||||
# GeViScope Connection
|
||||
GEVISCOPE_HOST=localhost
|
||||
GEVISCOPE_USERNAME=sysadmin
|
||||
GEVISCOPE_PASSWORD=masterkey
|
||||
|
||||
# SDK Bridge gRPC
|
||||
SDK_BRIDGE_HOST=localhost
|
||||
SDK_BRIDGE_PORT=50051
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_DB=0
|
||||
REDIS_PASSWORD=
|
||||
|
||||
# JWT Authentication
|
||||
JWT_SECRET_KEY=your-secret-key-change-in-production
|
||||
JWT_ALGORITHM=HS256
|
||||
JWT_ACCESS_TOKEN_EXPIRE_MINUTES=60
|
||||
JWT_REFRESH_TOKEN_EXPIRE_DAYS=7
|
||||
|
||||
# Stream URLs
|
||||
STREAM_BASE_URL=rtsp://localhost:8554
|
||||
STREAM_TOKEN_EXPIRE_MINUTES=15
|
||||
|
||||
# Logging
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FORMAT=json
|
||||
```
|
||||
|
||||
**Security Note**: Change `JWT_SECRET_KEY` and `GEVISCOPE_PASSWORD` in production!
|
||||
|
||||
### Database Migrations
|
||||
|
||||
```bash
|
||||
cd src/api
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Starting the Services
|
||||
|
||||
### 1. Start GeViServer
|
||||
```cmd
|
||||
cd C:\GEVISOFT
|
||||
GeViServer.exe console
|
||||
```
|
||||
|
||||
### 2. Start Redis
|
||||
```bash
|
||||
redis-server
|
||||
```
|
||||
|
||||
### 3. Start SDK Bridge
|
||||
```bash
|
||||
cd src/sdk-bridge
|
||||
dotnet run --configuration Release
|
||||
```
|
||||
|
||||
### 4. Start API Server
|
||||
```bash
|
||||
cd src/api
|
||||
uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
||||
```
|
||||
|
||||
**Verify Services**:
|
||||
- API: http://localhost:8000/api/v1/health
|
||||
- API Docs: http://localhost:8000/docs
|
||||
- SDK Bridge: gRPC on localhost:50051
|
||||
|
||||
---
|
||||
|
||||
## First API Call
|
||||
|
||||
### 1. Authenticate
|
||||
|
||||
**Request**:
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/api/v1/auth/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"username": "sysadmin",
|
||||
"password": "masterkey"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"token_type": "bearer",
|
||||
"expires_in": 3600
|
||||
}
|
||||
```
|
||||
|
||||
**Save the access token** - you'll need it for all subsequent requests.
|
||||
|
||||
### 2. List Cameras
|
||||
|
||||
**Request**:
|
||||
```bash
|
||||
curl -X GET "http://localhost:8000/api/v1/cameras" \
|
||||
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"total": 2,
|
||||
"page": 1,
|
||||
"page_size": 50,
|
||||
"cameras": [
|
||||
{
|
||||
"id": "550e8400-e29b-41d4-a716-446655440001",
|
||||
"channel": 1,
|
||||
"name": "Front Entrance",
|
||||
"description": "Main entrance camera",
|
||||
"status": "online",
|
||||
"capabilities": {
|
||||
"ptz": true,
|
||||
"audio": false,
|
||||
"analytics": ["motion_detection", "people_counting"]
|
||||
},
|
||||
"resolutions": [
|
||||
{"width": 1920, "height": 1080, "fps": 30},
|
||||
{"width": 1280, "height": 720, "fps": 60}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Start Video Stream
|
||||
|
||||
**Request**:
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/api/v1/cameras/550e8400-e29b-41d4-a716-446655440001/stream" \
|
||||
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"resolution": {"width": 1920, "height": 1080, "fps": 30},
|
||||
"format": "h264"
|
||||
}'
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```json
|
||||
{
|
||||
"stream_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
|
||||
"camera_id": "550e8400-e29b-41d4-a716-446655440001",
|
||||
"url": "rtsp://localhost:8554/stream/7c9e6679?token=eyJhbGc...",
|
||||
"format": "h264",
|
||||
"resolution": {"width": 1920, "height": 1080, "fps": 30},
|
||||
"started_at": "2025-12-08T15:30:00Z",
|
||||
"expires_at": "2025-12-08T15:45:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**Use the stream URL** in your video player (VLC, ffplay, etc.):
|
||||
```bash
|
||||
ffplay "rtsp://localhost:8554/stream/7c9e6679?token=eyJhbGc..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
### Python SDK Example
|
||||
|
||||
```python
|
||||
import requests
|
||||
from typing import Dict, Any
|
||||
|
||||
class GeutebruckAPI:
|
||||
def __init__(self, base_url: str = "http://localhost:8000"):
|
||||
self.base_url = base_url
|
||||
self.access_token = None
|
||||
|
||||
def login(self, username: str, password: str) -> Dict[str, Any]:
|
||||
"""Authenticate and get access token"""
|
||||
response = requests.post(
|
||||
f"{self.base_url}/api/v1/auth/login",
|
||||
json={"username": username, "password": password}
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
self.access_token = data["access_token"]
|
||||
return data
|
||||
|
||||
def get_cameras(self) -> Dict[str, Any]:
|
||||
"""List all cameras"""
|
||||
response = requests.get(
|
||||
f"{self.base_url}/api/v1/cameras",
|
||||
headers={"Authorization": f"Bearer {self.access_token}"}
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
def start_stream(self, camera_id: str, width: int = 1920, height: int = 1080) -> Dict[str, Any]:
|
||||
"""Start video stream from camera"""
|
||||
response = requests.post(
|
||||
f"{self.base_url}/api/v1/cameras/{camera_id}/stream",
|
||||
headers={"Authorization": f"Bearer {self.access_token}"},
|
||||
json={
|
||||
"resolution": {"width": width, "height": height, "fps": 30},
|
||||
"format": "h264"
|
||||
}
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
# Usage
|
||||
api = GeutebruckAPI()
|
||||
api.login("sysadmin", "masterkey")
|
||||
cameras = api.get_cameras()
|
||||
stream = api.start_stream(cameras["cameras"][0]["id"])
|
||||
print(f"Stream URL: {stream['url']}")
|
||||
```
|
||||
|
||||
### WebSocket Event Monitoring
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import websockets
|
||||
import json
|
||||
|
||||
async def monitor_events(access_token: str):
|
||||
"""Subscribe to real-time surveillance events"""
|
||||
uri = f"ws://localhost:8000/api/v1/events/stream?token={access_token}"
|
||||
|
||||
async with websockets.connect(uri) as websocket:
|
||||
# Subscribe to specific event types
|
||||
await websocket.send(json.dumps({
|
||||
"action": "subscribe",
|
||||
"filters": {
|
||||
"event_types": ["motion_detected", "alarm_triggered"],
|
||||
"camera_ids": ["550e8400-e29b-41d4-a716-446655440001"]
|
||||
}
|
||||
}))
|
||||
|
||||
# Receive events
|
||||
while True:
|
||||
message = await websocket.recv()
|
||||
event = json.loads(message)
|
||||
print(f"Event: {event['event_type']} on camera {event['camera_id']}")
|
||||
print(f" Timestamp: {event['timestamp']}")
|
||||
print(f" Details: {event['details']}")
|
||||
|
||||
# Run
|
||||
asyncio.run(monitor_events("YOUR_ACCESS_TOKEN"))
|
||||
```
|
||||
|
||||
### PTZ Camera Control
|
||||
|
||||
```bash
|
||||
# Move camera to preset position
|
||||
curl -X POST "http://localhost:8000/api/v1/cameras/550e8400-e29b-41d4-a716-446655440001/ptz" \
|
||||
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command": "goto_preset",
|
||||
"preset": 1
|
||||
}'
|
||||
|
||||
# Pan/tilt/zoom control
|
||||
curl -X POST "http://localhost:8000/api/v1/cameras/550e8400-e29b-41d4-a716-446655440001/ptz" \
|
||||
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"command": "move",
|
||||
"pan": 50,
|
||||
"tilt": 30,
|
||||
"zoom": 2.5,
|
||||
"speed": 50
|
||||
}'
|
||||
```
|
||||
|
||||
### Query Recordings
|
||||
|
||||
```python
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
def get_recordings(camera_id: str, access_token: str):
|
||||
"""Get recordings from last 24 hours"""
|
||||
end_time = datetime.utcnow()
|
||||
start_time = end_time - timedelta(hours=24)
|
||||
|
||||
response = requests.get(
|
||||
"http://localhost:8000/api/v1/recordings",
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
params={
|
||||
"camera_id": camera_id,
|
||||
"start_time": start_time.isoformat() + "Z",
|
||||
"end_time": end_time.isoformat() + "Z",
|
||||
"event_type": "motion_detected"
|
||||
}
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
# Usage
|
||||
recordings = get_recordings("550e8400-e29b-41d4-a716-446655440001", "YOUR_ACCESS_TOKEN")
|
||||
for rec in recordings["recordings"]:
|
||||
print(f"Recording: {rec['start_time']} - {rec['end_time']}")
|
||||
print(f" Size: {rec['size_bytes'] / 1024 / 1024:.2f} MB")
|
||||
print(f" Export URL: {rec['export_url']}")
|
||||
```
|
||||
|
||||
### Configure Video Analytics
|
||||
|
||||
```bash
|
||||
# Enable motion detection
|
||||
curl -X POST "http://localhost:8000/api/v1/analytics/550e8400-e29b-41d4-a716-446655440001" \
|
||||
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"type": "motion_detection",
|
||||
"enabled": true,
|
||||
"configuration": {
|
||||
"sensitivity": 75,
|
||||
"regions": [
|
||||
{
|
||||
"name": "entrance",
|
||||
"points": [
|
||||
{"x": 100, "y": 100},
|
||||
{"x": 500, "y": 100},
|
||||
{"x": 500, "y": 400},
|
||||
{"x": 100, "y": 400}
|
||||
]
|
||||
}
|
||||
],
|
||||
"schedule": {
|
||||
"enabled": true,
|
||||
"start_time": "18:00:00",
|
||||
"end_time": "06:00:00",
|
||||
"days": [1, 2, 3, 4, 5, 6, 7]
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
### Run Unit Tests
|
||||
|
||||
```bash
|
||||
cd src/api
|
||||
pytest tests/unit -v --cov=app --cov-report=html
|
||||
```
|
||||
|
||||
### Run Integration Tests
|
||||
|
||||
```bash
|
||||
# Requires running GeViServer and SDK Bridge
|
||||
pytest tests/integration -v
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
|
||||
Minimum 80% coverage enforced. View coverage report:
|
||||
```bash
|
||||
# Open coverage report
|
||||
start htmlcov/index.html # Windows
|
||||
open htmlcov/index.html # macOS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API Documentation
|
||||
|
||||
### Interactive Docs
|
||||
|
||||
Once the API is running, visit:
|
||||
|
||||
- **Swagger UI**: http://localhost:8000/docs
|
||||
- **ReDoc**: http://localhost:8000/redoc
|
||||
- **OpenAPI JSON**: http://localhost:8000/openapi.json
|
||||
|
||||
### Complete API Reference
|
||||
|
||||
See [contracts/openapi.yaml](./contracts/openapi.yaml) for the complete OpenAPI 3.0 specification.
|
||||
|
||||
### Data Model
|
||||
|
||||
See [data-model.md](./data-model.md) for entity schemas, relationships, and validation rules.
|
||||
|
||||
### Architecture
|
||||
|
||||
See [research.md](./research.md) for:
|
||||
- System architecture decisions
|
||||
- SDK integration patterns
|
||||
- Performance considerations
|
||||
- Security implementation
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**1. "Could not load file or assembly 'GeViProcAPINET_4_0.dll'"**
|
||||
|
||||
**Solution**: Install Visual C++ 2010 Redistributable (x86):
|
||||
```powershell
|
||||
Invoke-WebRequest -Uri 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe' -OutFile 'vcredist_x86_2010.exe'
|
||||
Start-Process -FilePath 'vcredist_x86_2010.exe' -ArgumentList '/install', '/quiet', '/norestart' -Wait
|
||||
```
|
||||
|
||||
**2. "Connection refused to GeViServer"**
|
||||
|
||||
**Solution**: Ensure GeViServer is running:
|
||||
```cmd
|
||||
cd C:\GEVISOFT
|
||||
GeViServer.exe console
|
||||
```
|
||||
Check ports: `netstat -an | findstr "7700 7701 7703"`
|
||||
|
||||
**3. "Redis connection failed"**
|
||||
|
||||
**Solution**: Start Redis server:
|
||||
```bash
|
||||
redis-server
|
||||
```
|
||||
|
||||
**4. "SDK Bridge gRPC not responding"**
|
||||
|
||||
**Solution**: Check SDK Bridge logs and restart:
|
||||
```bash
|
||||
cd src/sdk-bridge
|
||||
dotnet run --configuration Release
|
||||
```
|
||||
|
||||
**5. "401 Unauthorized" on API calls**
|
||||
|
||||
**Solution**: Check your access token hasn't expired (1 hour lifetime). Use refresh token to get new access token:
|
||||
```bash
|
||||
curl -X POST "http://localhost:8000/api/v1/auth/refresh" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"refresh_token": "YOUR_REFRESH_TOKEN"
|
||||
}'
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging:
|
||||
```env
|
||||
LOG_LEVEL=DEBUG
|
||||
```
|
||||
|
||||
View logs:
|
||||
```bash
|
||||
# API logs
|
||||
tail -f logs/api.log
|
||||
|
||||
# SDK Bridge logs
|
||||
tail -f src/sdk-bridge/logs/bridge.log
|
||||
```
|
||||
|
||||
### Health Check
|
||||
|
||||
```bash
|
||||
# API health
|
||||
curl http://localhost:8000/api/v1/health
|
||||
|
||||
# Expected response
|
||||
{
|
||||
"status": "healthy",
|
||||
"timestamp": "2025-12-08T15:30:00Z",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"sdk_bridge": "connected",
|
||||
"redis": "connected",
|
||||
"database": "connected"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Tuning
|
||||
|
||||
### Response Time Optimization
|
||||
|
||||
**Target**: <200ms for most endpoints
|
||||
|
||||
```env
|
||||
# Connection pooling
|
||||
SDK_BRIDGE_POOL_SIZE=10
|
||||
SDK_BRIDGE_MAX_OVERFLOW=20
|
||||
|
||||
# Redis connection pool
|
||||
REDIS_MAX_CONNECTIONS=50
|
||||
|
||||
# Async workers
|
||||
UVICORN_WORKERS=4
|
||||
```
|
||||
|
||||
### WebSocket Scaling
|
||||
|
||||
**Target**: 1000+ concurrent connections
|
||||
|
||||
```env
|
||||
# Redis pub/sub
|
||||
REDIS_PUBSUB_MAX_CONNECTIONS=100
|
||||
|
||||
# WebSocket timeouts
|
||||
WEBSOCKET_PING_INTERVAL=30
|
||||
WEBSOCKET_PING_TIMEOUT=10
|
||||
```
|
||||
|
||||
### Stream URL Caching
|
||||
|
||||
Stream URLs are cached for token lifetime (15 minutes) to reduce SDK bridge calls.
|
||||
|
||||
---
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### Production Deployment
|
||||
|
||||
**CRITICAL**: Before deploying to production:
|
||||
|
||||
1. **Change default credentials**:
|
||||
```env
|
||||
GEVISCOPE_PASSWORD=your-secure-password-here
|
||||
JWT_SECRET_KEY=generate-with-openssl-rand-hex-32
|
||||
REDIS_PASSWORD=your-redis-password
|
||||
```
|
||||
|
||||
2. **Enable HTTPS**:
|
||||
- Use reverse proxy (nginx/Caddy) with SSL certificates
|
||||
- Redirect HTTP to HTTPS
|
||||
|
||||
3. **Network security**:
|
||||
- GeViServer should NOT be exposed to internet
|
||||
- API should be behind firewall/VPN
|
||||
- Use internal network for SDK Bridge ↔ GeViServer communication
|
||||
|
||||
4. **Rate limiting**:
|
||||
```env
|
||||
RATE_LIMIT_PER_MINUTE=60
|
||||
RATE_LIMIT_BURST=10
|
||||
```
|
||||
|
||||
5. **Audit logging**:
|
||||
```env
|
||||
AUDIT_LOG_ENABLED=true
|
||||
AUDIT_LOG_PATH=/var/log/geutebruck-api/audit.log
|
||||
```
|
||||
|
||||
See [security.md](./security.md) for complete security guidelines.
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Read the Architecture**: [research.md](./research.md) - Understanding system design decisions
|
||||
2. **Explore Data Model**: [data-model.md](./data-model.md) - Entity schemas and relationships
|
||||
3. **API Reference**: [contracts/openapi.yaml](./contracts/openapi.yaml) - Complete endpoint documentation
|
||||
4. **SDK Integration**: [../../SDK_INTEGRATION_LESSONS.md](../../SDK_INTEGRATION_LESSONS.md) - Deep dive into SDK usage
|
||||
5. **Join Development**: [CONTRIBUTING.md](../../CONTRIBUTING.md) - Contributing guidelines
|
||||
|
||||
---
|
||||
|
||||
## Support
|
||||
|
||||
- **Issues**: https://github.com/your-org/geutebruck-api/issues
|
||||
- **Documentation**: https://docs.geutebruck-api.example.com
|
||||
- **GeViScope SDK**: See `C:\GEVISOFT\Documentation\`
|
||||
|
||||
---
|
||||
|
||||
**Version**: 1.0.0
|
||||
**Last Updated**: 2025-12-08
|
||||
1024
geutebruck-api/specs/001-surveillance-api/research.md
Normal file
1024
geutebruck-api/specs/001-surveillance-api/research.md
Normal file
File diff suppressed because it is too large
Load Diff
485
geutebruck-api/specs/001-surveillance-api/spec.md
Normal file
485
geutebruck-api/specs/001-surveillance-api/spec.md
Normal file
@@ -0,0 +1,485 @@
|
||||
# Feature Specification: Geutebruck Unified Video Surveillance API
|
||||
|
||||
**Feature Branch**: `001-surveillance-api`
|
||||
**Created**: 2025-11-13
|
||||
**Updated**: 2025-12-16 (Configuration Management + Critical Bug Fixes)
|
||||
**Status**: In Progress
|
||||
**Input**: "Complete RESTful API for Geutebruck GeViSoft/GeViScope unified video surveillance system control with multi-instance support"
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
This API provides a **unified interface** to control both GeViSoft (management platform) and multiple GeViScope instances (video servers):
|
||||
|
||||
```
|
||||
Geutebruck Unified API
|
||||
│
|
||||
├── GeViSoft Layer (Management)
|
||||
│ └── GeViServer Connection
|
||||
│ ├── System-wide alarm management
|
||||
│ ├── Event coordination across GeViScope instances
|
||||
│ ├── Action mapping and automation
|
||||
│ └── Cross-system orchestration
|
||||
│
|
||||
└── GeViScope Layer (Video Operations)
|
||||
├── GeViScope Instance "main" (GSCServer - localhost)
|
||||
│ ├── Cameras: 101027-101041
|
||||
│ └── Monitors: 1-256
|
||||
├── GeViScope Instance "parking" (GSCServer - 192.168.1.100)
|
||||
│ ├── Cameras: 201001-201020
|
||||
│ └── Monitors: 1-64
|
||||
└── GeViScope Instance "warehouse" (GSCServer - 192.168.1.101)
|
||||
├── Cameras: 301001-301050
|
||||
└── Monitors: 1-128
|
||||
```
|
||||
|
||||
**Key Concepts:**
|
||||
- **GeViSoft** = Management platform controlling multiple GeViScope instances (1 per system)
|
||||
- **GeViScope** = Video server instances handling cameras, monitors, video routing (N per system)
|
||||
- **Monitors (Video Outputs)** = Logical display channels (NOT physical displays, require viewer apps)
|
||||
- **CrossSwitch** = Video routing command (camera → monitor at server level)
|
||||
- **GSCView** = Viewer application that displays video outputs
|
||||
|
||||
## User Scenarios & Testing *(mandatory)*
|
||||
|
||||
### User Story 1 - Secure API Access (Priority: P1)
|
||||
|
||||
As a developer integrating a custom surveillance application, I need to authenticate to the API securely so that only authorized users can access camera feeds and control functions.
|
||||
|
||||
**Why this priority**: Without authentication, the entire system is insecure and unusable. This is the foundation for all other features and must be implemented first.
|
||||
|
||||
**Independent Test**: Can be fully tested by attempting to access protected endpoints without credentials (should fail), then with valid JWT tokens (should succeed), and delivers a working authentication system that all other features depend on.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** a developer with valid credentials, **When** they request a JWT token from `/api/v1/auth/login`, **Then** they receive a token valid for 1 hour with appropriate user claims
|
||||
2. **Given** an expired JWT token, **When** they attempt to access a protected endpoint, **Then** they receive a 401 Unauthorized response with clear error message
|
||||
3. **Given** a valid refresh token, **When** they request a new access token, **Then** they receive a fresh JWT token without re-authenticating
|
||||
4. **Given** invalid credentials, **When** they attempt to login, **Then** they receive a 401 response and the failed attempt is logged for security monitoring
|
||||
|
||||
---
|
||||
|
||||
### User Story 2 - Multi-Instance GeViScope Management (Priority: P1)
|
||||
|
||||
As a system administrator, I need to manage multiple GeViScope instances through a single API so that I can control video operations across different locations and servers.
|
||||
|
||||
**Why this priority**: Multi-instance support is core to the unified architecture. Without it, the API can only control one GeViScope server, limiting scalability.
|
||||
|
||||
**Independent Test**: Can be fully tested by configuring multiple GeViScope instances, querying available instances, and executing operations on specific instances.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** three GeViScope instances configured (main, parking, warehouse), **When** a user requests `/api/v1/geviscope/instances`, **Then** they receive a list of all instances with status, camera count, and connection state
|
||||
2. **Given** operations targeting a specific instance, **When** a user calls `/api/v1/geviscope/parking/cameras`, **Then** they receive only cameras from the parking instance
|
||||
3. **Given** a default instance configured, **When** a user calls `/api/v1/cameras` without instance ID, **Then** the request routes to the default instance
|
||||
4. **Given** one GeViScope instance is offline, **When** operations target that instance, **Then** the API returns clear error messages while other instances remain operational
|
||||
|
||||
---
|
||||
|
||||
### User Story 3 - Video CrossSwitch and Monitor Control (Priority: P1)
|
||||
|
||||
As a security operator, I need to route camera video feeds to specific monitors via CrossSwitch commands so that I can dynamically control what video appears on display systems.
|
||||
|
||||
**Why this priority**: CrossSwitch is the core video routing mechanism in GeViScope systems. Without it, operators cannot control video distribution to displays.
|
||||
|
||||
**Independent Test**: Can be fully tested by executing CrossSwitch commands to route cameras to monitors, verifying routes in the routing table, and clearing monitor assignments.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** camera 101038 and monitor 1 exist, **When** an operator sends `POST /api/v1/crossswitch` with `{camera_id: 101038, monitor_id: 1}`, **Then** the camera video is routed to monitor 1 at the server level and a route record is created
|
||||
2. **Given** an active route exists, **When** an operator queries `/api/v1/crossswitch/routing`, **Then** they receive a list of all active camera→monitor routes with timestamps and user who created them
|
||||
3. **Given** a monitor displaying video, **When** an operator sends `DELETE /api/v1/crossswitch/{monitor_id}`, **Then** the monitor is cleared and the route is marked inactive
|
||||
4. **Given** multiple monitors in a monitor group, **When** an alarm triggers CrossSwitch actions, **Then** all designated cameras are routed to their assigned monitors automatically
|
||||
|
||||
---
|
||||
|
||||
### User Story 4 - Live Video Stream Access (Priority: P1)
|
||||
|
||||
As a security operator, I need to view live video streams from surveillance cameras through the API so that I can monitor locations in real-time from a custom dashboard.
|
||||
|
||||
**Why this priority**: Live video viewing is the core function of surveillance systems. Without this, the system cannot fulfill its primary purpose.
|
||||
|
||||
**Independent Test**: Can be fully tested by requesting stream URLs for configured cameras and verifying that video playback works, delivering immediate value as a basic surveillance viewer.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated user with camera view permissions, **When** they request a live stream for camera 101038, **Then** they receive a stream URL that delivers live video within 2 seconds
|
||||
2. **Given** a camera that is offline, **When** a user requests its stream, **Then** they receive a clear error message indicating the camera is unavailable
|
||||
3. **Given** multiple concurrent users, **When** they request the same camera stream, **Then** all users can view the stream simultaneously without degradation (up to 100 concurrent streams)
|
||||
4. **Given** a user without permission for a specific camera, **When** they request its stream, **Then** they receive a 403 Forbidden response
|
||||
|
||||
---
|
||||
|
||||
### User Story 5 - Camera PTZ Control (Priority: P1)
|
||||
|
||||
As a security operator, I need to control pan-tilt-zoom cameras remotely via the API so that I can adjust camera angles to investigate incidents or track movement.
|
||||
|
||||
**Why this priority**: PTZ control is essential for active surveillance operations and incident response, making it critical for operational use.
|
||||
|
||||
**Independent Test**: Can be fully tested by sending PTZ commands (pan left/right, tilt up/down, zoom in/out) to a PTZ-capable camera and verifying movement occurs, delivering functional camera control capabilities.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated operator with PTZ permissions, **When** they send a pan-left command to camera 101038, **Then** the camera begins moving left within 500ms and they receive confirmation
|
||||
2. **Given** a camera that doesn't support PTZ, **When** a user attempts PTZ control, **Then** they receive a clear error indicating PTZ is not available for this camera
|
||||
3. **Given** two operators controlling the same PTZ camera, **When** they send conflicting commands simultaneously, **Then** the system queues commands and notifies operators of the conflict
|
||||
4. **Given** a PTZ command in progress, **When** the user sends a stop command, **Then** the camera movement stops immediately
|
||||
|
||||
---
|
||||
|
||||
### User Story 6 - Real-time Event Notifications (Priority: P1)
|
||||
|
||||
As a security operator, I need to receive instant notifications when surveillance events occur (motion detection, alarms, sensor triggers) so that I can respond quickly to security incidents.
|
||||
|
||||
**Why this priority**: Real-time alerts are critical for security effectiveness. Without event notifications, operators must constantly monitor all cameras manually.
|
||||
|
||||
**Independent Test**: Can be fully tested by subscribing to event notifications via WebSocket, triggering a test alarm, and verifying notification delivery within 100ms, providing functional event monitoring.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated user with event subscription permissions, **When** they connect to `/api/v1/events/stream`, **Then** they receive a connection confirmation and can subscribe to specific event types
|
||||
2. **Given** a motion detection event occurs on camera 101038, **When** a subscribed user is listening for video analytics events, **Then** they receive a notification within 100ms containing event type, camera ID, GeViScope instance, timestamp, and relevant data
|
||||
3. **Given** a network disconnection, **When** the WebSocket reconnects, **Then** the user automatically re-subscribes and receives any missed critical events
|
||||
4. **Given** events from multiple GeViScope instances, **When** subscribed users receive notifications, **Then** each event clearly indicates which instance it originated from
|
||||
|
||||
---
|
||||
|
||||
### User Story 7 - GeViSoft Alarm Management (Priority: P2)
|
||||
|
||||
As a security administrator, I need to configure and manage alarms in GeViSoft so that I can automate responses to security events across multiple GeViScope instances.
|
||||
|
||||
**Why this priority**: Important for advanced automation but basic video operations must work first. Alarms coordinate actions across the system.
|
||||
|
||||
**Independent Test**: Can be fully tested by creating an alarm configuration, triggering the alarm via an event, and verifying that configured actions (CrossSwitch, notifications) execute correctly.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated administrator, **When** they create an alarm with start/stop/acknowledge actions, **Then** the alarm is saved in GeViSoft and can be triggered by configured events
|
||||
2. **Given** an alarm configured to route cameras 101038 and 101039 to monitors 1-2, **When** the alarm triggers, **Then** CrossSwitch actions execute and cameras appear on designated monitors
|
||||
3. **Given** an active alarm, **When** an operator acknowledges it via `/api/v1/gevisoft/alarms/{alarm_id}/acknowledge`, **Then** acknowledge actions execute and alarm state updates
|
||||
4. **Given** multiple GeViScope instances, **When** an alarm spans instances (e.g., camera from instance A to monitor in instance B), **Then** the API coordinates cross-instance operations
|
||||
|
||||
---
|
||||
|
||||
### User Story 8 - Monitor and Viewer Management (Priority: P2)
|
||||
|
||||
As a system administrator, I need to query and manage video output monitors so that I can understand system topology and configure video routing.
|
||||
|
||||
**Why this priority**: Enhances system visibility and configuration but video operations can work without detailed monitor management initially.
|
||||
|
||||
**Independent Test**: Can be fully tested by querying monitor lists, checking monitor status, and understanding which cameras are currently routed to which monitors.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** 256 monitors configured in a GeViScope instance, **When** an administrator queries `/api/v1/geviscope/main/monitors`, **Then** they receive a list of all monitors with IDs, names, status, and current camera assignments
|
||||
2. **Given** a monitor displaying video, **When** queried for current assignment, **Then** the API returns which camera is currently routed to that monitor
|
||||
3. **Given** multiple GeViScope instances, **When** listing monitors, **Then** each instance's monitors are clearly identified by instance ID
|
||||
4. **Given** GSCView viewers connected to monitors, **When** administrators query viewer status, **Then** they can see which viewers are active and what they're displaying
|
||||
|
||||
---
|
||||
|
||||
### User Story 9 - Recording Management (Priority: P2)
|
||||
|
||||
As a security administrator, I need to manage video recording settings and query recorded footage so that I can configure retention policies and retrieve historical video for investigations.
|
||||
|
||||
**Why this priority**: Important for compliance and investigations but not required for basic live monitoring. Can be added after core live viewing is functional.
|
||||
|
||||
**Independent Test**: Can be fully tested by configuring recording schedules, starting/stopping recording on specific cameras, and querying recorded footage by time range, delivering complete recording management.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated administrator, **When** they request recording start on camera 101038, **Then** the camera begins recording and they receive confirmation with recording ID
|
||||
2. **Given** a time range query for 2025-11-12 14:00 to 16:00 on camera 101038, **When** an investigator searches for recordings, **Then** they receive a list of available recording segments with playback URLs
|
||||
3. **Given** the ring buffer is at 90% capacity, **When** an administrator checks recording capacity, **Then** they receive an alert indicating low storage and oldest recordings that will be overwritten
|
||||
4. **Given** scheduled recording configured for nighttime hours, **When** the schedule time arrives, **Then** recording automatically starts and stops according to the schedule
|
||||
|
||||
---
|
||||
|
||||
### User Story 10 - Video Analytics Configuration (Priority: P2)
|
||||
|
||||
As a security administrator, I need to configure video content analysis features (motion detection, object tracking, perimeter protection) so that the system can automatically detect security-relevant events.
|
||||
|
||||
**Why this priority**: Enhances system capabilities but requires basic video viewing to already be working. Analytics configuration is valuable but not essential for day-one operation.
|
||||
|
||||
**Independent Test**: Can be fully tested by configuring motion detection zones on a camera, triggering motion, and verifying analytics events are generated, delivering automated detection capabilities.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated administrator, **When** they configure motion detection zones on camera 101038, **Then** the configuration is saved and motion detection activates within those zones
|
||||
2. **Given** motion detection configured with sensitivity level 7, **When** motion occurs in the detection zone, **Then** a motion detection event is generated and sent to event subscribers
|
||||
3. **Given** object tracking enabled on camera 101038, **When** a person enters the frame, **Then** the system assigns a tracking ID and sends position updates for the duration they remain visible
|
||||
4. **Given** multiple analytics enabled on one camera (VMD + OBTRACK), **When** events occur, **Then** all configured analytics generate appropriate events without interfering with each other
|
||||
|
||||
---
|
||||
|
||||
### User Story 11 - Action Mapping and Automation (Priority: P3)
|
||||
|
||||
As a security administrator, I need to configure action mappings in GeViSoft so that specific events automatically trigger corresponding actions across the system.
|
||||
|
||||
**Why this priority**: Valuable for automation but requires basic event and action functionality to be working first.
|
||||
|
||||
**Independent Test**: Can be fully tested by creating an action mapping (e.g., motion detected → CrossSwitch), triggering the input action, and verifying the mapped actions execute.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an action mapping configured (InputContact closed → CrossSwitch cameras to monitors), **When** the input contact event occurs, **Then** the mapped CrossSwitch actions execute automatically
|
||||
2. **Given** multiple output actions mapped to one input, **When** the input event triggers, **Then** all output actions execute in sequence
|
||||
3. **Given** action mappings spanning GeViScope instances, **When** triggered, **Then** the API coordinates actions across instances correctly
|
||||
4. **Given** an action mapping fails (e.g., target camera offline), **When** execution occurs, **Then** errors are logged and administrators are notified without blocking other actions
|
||||
|
||||
---
|
||||
|
||||
### User Story 12 - GeViSoft Configuration Management (Priority: P1) ✅ IMPLEMENTED
|
||||
|
||||
As a system administrator, I need to manage GeViSoft configuration (G-Core servers, action mappings) via the API so that I can programmatically configure and maintain the surveillance system without manual GeViSet operations.
|
||||
|
||||
**Why this priority**: Configuration management is essential for automation, infrastructure-as-code, and maintaining consistent configurations across environments.
|
||||
|
||||
**Independent Test**: Can be fully tested by creating/reading/updating/deleting servers and action mappings, verifying changes persist in GeViSoft, and confirming no data loss occurs.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** an authenticated administrator, **When** they create a new G-Core server via `POST /api/v1/configuration/servers`, **Then** the server is added to GeViSoft configuration with correct bool types and appears in GeViSet
|
||||
2. **Given** existing servers in configuration, **When** an administrator queries `/api/v1/configuration/servers`, **Then** they receive a list of all servers with IDs, aliases, hosts, and connection settings
|
||||
3. **Given** multiple action mappings to delete, **When** deletion occurs in reverse order (highest ID first), **Then** only intended mappings are deleted without cascade deletion
|
||||
4. **Given** a server ID auto-increment requirement, **When** creating servers, **Then** the system automatically assigns the next available numeric ID based on existing servers
|
||||
|
||||
**Implementation Status** (2025-12-16):
|
||||
- ✅ Server CRUD: CREATE, READ, DELETE working; UPDATE has known bug
|
||||
- ✅ Action Mapping CRUD: CREATE, READ, UPDATE, DELETE all working
|
||||
- ✅ Critical Fix: Cascade deletion bug fixed (delete in reverse order)
|
||||
- ✅ Configuration tree navigation and parsing
|
||||
- ✅ SetupClient integration for configuration download/upload
|
||||
- ✅ Bool type handling for server fields (Enabled, DeactivateEcho, DeactivateLiveCheck)
|
||||
- ⚠️ Known Issue: Server UpdateServer method requires bug fix for "Server ID is required" error
|
||||
|
||||
**Documentation**:
|
||||
- SERVER_CRUD_IMPLEMENTATION.md
|
||||
- CRITICAL_BUG_FIX_DELETE.md
|
||||
|
||||
---
|
||||
|
||||
### User Story 13 - System Health Monitoring (Priority: P3)
|
||||
|
||||
As a system administrator, I need to monitor API and surveillance system health status so that I can proactively identify and resolve issues before they impact operations.
|
||||
|
||||
**Why this priority**: Important for production systems but not required for initial deployment. Health monitoring is an operational enhancement that can be added incrementally.
|
||||
|
||||
**Independent Test**: Can be fully tested by querying the health endpoint, checking SDK connectivity status for all instances, and verifying alerts when components fail.
|
||||
|
||||
**Acceptance Scenarios**:
|
||||
|
||||
1. **Given** the API is running, **When** an unauthenticated user requests `/api/v1/health`, **Then** they receive system status including API uptime, GeViSoft connectivity, all GeViScope instance statuses, and overall health score
|
||||
2. **Given** one GeViScope instance fails, **When** health is checked, **Then** the health endpoint returns degraded status with specific instance error details while other instances show healthy
|
||||
3. **Given** disk space for recordings drops below 10%, **When** monitoring checks run, **Then** a warning is included in health status and administrators receive notification
|
||||
4. **Given** an administrator monitoring performance, **When** they request detailed metrics, **Then** they receive statistics on request throughput, active streams per instance, and connection status for all instances
|
||||
|
||||
---
|
||||
|
||||
### Edge Cases
|
||||
|
||||
- What happens when a GeViScope instance disconnects while operators are viewing cameras from that instance?
|
||||
- How does CrossSwitch behave when routing a camera from one GeViScope instance to a monitor on a different instance (if supported)?
|
||||
- What occurs when GeViSoft connection fails but GeViScope instances remain online?
|
||||
- How does the API handle monitor IDs that overlap across different GeViScope instances?
|
||||
- What happens when a GSCView viewer is configured to display a monitor that has no active camera route?
|
||||
- How does the system respond when CrossSwitch commands execute successfully at the server but no viewer is displaying the monitor?
|
||||
- What occurs when an alarm in GeViSoft references cameras or monitors from a GeViScope instance that is offline?
|
||||
- How does the API handle time synchronization issues between GeViSoft, multiple GeViScope instances, and the API server?
|
||||
- What happens when monitor enumeration returns different results than expected (e.g., 256 monitors vs 16 actual video outputs)?
|
||||
- How does the system handle authentication when GeViSoft credentials differ from GeViScope credentials?
|
||||
|
||||
## Requirements *(mandatory)*
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
**Architecture & Multi-Instance:**
|
||||
- **FR-001**: System MUST support connecting to one GeViSoft instance (GeViServer) for management operations
|
||||
- **FR-002**: System MUST support connecting to multiple GeViScope instances (GSCServer) with configurable instance IDs, hostnames, and credentials
|
||||
- **FR-003**: System MUST provide instance discovery endpoint listing all configured GeViScope instances with connection status
|
||||
- **FR-004**: System MUST support default instance configuration for convenience endpoints without instance ID
|
||||
- **FR-005**: System MUST clearly identify which GeViScope instance each resource (camera, monitor, event) belongs to
|
||||
|
||||
**Authentication & Authorization:**
|
||||
- **FR-006**: System MUST authenticate all API requests using JWT tokens with configurable expiration (default 1 hour for access, 7 days for refresh)
|
||||
- **FR-007**: System MUST implement role-based access control with roles: viewer (read-only), operator (control), administrator (full configuration)
|
||||
- **FR-008**: System MUST provide granular permissions allowing access restriction per camera, monitor, and GeViScope instance
|
||||
- **FR-009**: System MUST audit log all authentication attempts and privileged operations
|
||||
|
||||
**CrossSwitch & Monitor Management:**
|
||||
- **FR-010**: System MUST provide CrossSwitch endpoint to route cameras to monitors: `POST /api/v1/crossswitch` and instance-specific variant
|
||||
- **FR-011**: System MUST track active CrossSwitch routes in database with camera ID, monitor ID, mode, timestamp, and user
|
||||
- **FR-012**: System MUST provide endpoint to clear monitor assignments: `DELETE /api/v1/crossswitch/{monitor_id}`
|
||||
- **FR-013**: System MUST provide routing status endpoint showing all active camera→monitor routes
|
||||
- **FR-014**: System MUST use typed SDK actions (GeViAct_CrossSwitch) instead of string-based commands for reliable execution
|
||||
- **FR-015**: System MUST enumerate and expose all video output monitors with IDs, names, status, and current assignments
|
||||
- **FR-016**: System MUST support monitor grouping and bulk operations on monitor groups
|
||||
|
||||
**Video Operations:**
|
||||
- **FR-017**: System MUST expose live video streams for all cameras with initialization time under 2 seconds
|
||||
- **FR-018**: System MUST support PTZ control operations with command response time under 500ms
|
||||
- **FR-019**: System MUST handle concurrent video stream requests from minimum 100 simultaneous users
|
||||
- **FR-020**: System MUST gracefully handle camera offline scenarios with appropriate error codes
|
||||
|
||||
**Event Management:**
|
||||
- **FR-021**: System MUST provide WebSocket endpoint for real-time event notifications with delivery latency under 100ms
|
||||
- **FR-022**: System MUST support event subscriptions by type, camera, and GeViScope instance
|
||||
- **FR-023**: System MUST handle events from multiple GeViScope instances with clear instance identification
|
||||
- **FR-024**: System MUST support WebSocket connections from minimum 1000 concurrent clients
|
||||
|
||||
**GeViSoft Integration:**
|
||||
- **FR-025**: System MUST provide alarm management endpoints for GeViSoft alarm configuration and triggering
|
||||
- **FR-026**: System MUST support action mapping configuration and execution
|
||||
- **FR-027**: System MUST coordinate cross-instance operations when alarms or actions span multiple GeViScope instances
|
||||
- **FR-028**: System MUST provide endpoints for querying and managing GeViSoft system configuration
|
||||
|
||||
**Configuration Management:** ✅ IMPLEMENTED (2025-12-16)
|
||||
- **FR-039**: System MUST provide CRUD operations for G-Core server management with proper bool type handling
|
||||
- **FR-040**: System MUST provide CRUD operations for action mapping management
|
||||
- **FR-041**: System MUST delete multiple action mappings in reverse order (highest ID first) to prevent cascade deletion
|
||||
- **FR-042**: System MUST auto-increment server IDs based on highest existing numeric ID
|
||||
- **FR-043**: System MUST persist configuration changes to GeViSoft and verify changes are visible in GeViSet
|
||||
- **FR-044**: System MUST parse and navigate GeViSoft configuration tree structure (.set file format)
|
||||
- **FR-045**: System MUST use SetupClient for reliable configuration download/upload operations
|
||||
|
||||
**Recording & Analytics:**
|
||||
- **FR-029**: System MUST provide recording management including start/stop, queries, and capacity metrics
|
||||
- **FR-030**: System MUST support video analytics configuration (VMD, OBTRACK, NPR, G-Tect) where hardware supports
|
||||
- **FR-031**: System MUST provide query capabilities for recorded footage by channel, time range, and event association
|
||||
- **FR-032**: System MUST export video segments in standard formats (MP4/AVI) with metadata
|
||||
|
||||
**System Management:**
|
||||
- **FR-033**: System MUST provide health check endpoint returning status for GeViSoft, all GeViScope instances, database, and SDK bridges
|
||||
- **FR-034**: System MUST implement retry logic for transient SDK communication failures (3 attempts with exponential backoff)
|
||||
- **FR-035**: System MUST serve auto-generated OpenAPI/Swagger documentation at `/docs`
|
||||
- **FR-036**: System MUST support API versioning in URL path (v1, v2) for backward compatibility
|
||||
- **FR-037**: System MUST rate limit authentication attempts (max 5/minute per IP)
|
||||
- **FR-038**: System MUST enforce TLS 1.2+ for all API communication in production
|
||||
|
||||
### Key Entities
|
||||
|
||||
- **GeViScope Instance**: Configuration for a GSCServer connection with ID, hostname, credentials, status, camera count, monitor count
|
||||
- **Camera**: Video input channel with ID, global ID, name, GeViScope instance, capabilities, status, stream URL
|
||||
- **Monitor (Video Output)**: Logical display channel with ID, name, GeViScope instance, status, current camera assignment
|
||||
- **CrossSwitch Route**: Video routing record with camera ID, monitor ID, mode, GeViScope instance, created timestamp, created by user, active status
|
||||
- **User**: Authentication entity with username, password hash, role, permissions, JWT tokens, audit trail
|
||||
- **Event**: Surveillance occurrence with type, event ID, camera, GeViScope instance, timestamp, severity, data, foreign key
|
||||
- **Alarm (GeViSoft)**: System-wide alarm with ID, name, priority, monitor group, cameras, trigger actions, active status
|
||||
- **Action Mapping**: Automation rule with input action, output actions, GeViScope instance scope
|
||||
- **Recording**: Video footage segment with camera, GeViScope instance, start/end time, file size, trigger type
|
||||
- **Audit Log Entry**: Security record with timestamp, user, action, target resource, GeViScope instance, outcome
|
||||
|
||||
## Success Criteria *(mandatory)*
|
||||
|
||||
### Measurable Outcomes
|
||||
|
||||
- **SC-001**: Developers can authenticate and make their first successful API call within 10 minutes
|
||||
- **SC-002**: Operators can execute CrossSwitch to route cameras to monitors with routes visible in system within 1 second
|
||||
- **SC-003**: Multi-instance operations work correctly with 3+ GeViScope instances configured
|
||||
- **SC-004**: Security operators can view live video from any authorized camera with video appearing within 2 seconds
|
||||
- **SC-005**: PTZ camera movements respond to commands within 500ms
|
||||
- **SC-006**: Real-time event notifications delivered within 100ms across all GeViScope instances
|
||||
- **SC-007**: System supports 100 concurrent video streams across all instances without degradation
|
||||
- **SC-008**: System handles 1000+ concurrent WebSocket connections with 99.9% message delivery
|
||||
- **SC-009**: CrossSwitch routes created via API are visible in GeViAPI Test Client and affect GSCView displays
|
||||
- **SC-010**: API maintains 99.9% uptime with automatic failover if one GeViScope instance fails
|
||||
|
||||
### Business Impact
|
||||
|
||||
- **BI-001**: Custom surveillance applications can be developed in under 1 week using the API
|
||||
- **BI-002**: Support for multiple GeViScope instances enables scalable multi-site deployments
|
||||
- **BI-003**: Unified API reduces integration complexity by 70% compared to separate GeViSoft/GeViScope integrations
|
||||
- **BI-004**: CrossSwitch automation reduces operator workload for video routing by 80%
|
||||
|
||||
## Dependencies *(mandatory)*
|
||||
|
||||
### External Dependencies
|
||||
|
||||
- **GeViScope SDK 7.9.975.68+**: Core SDK for video operations
|
||||
- **GeViSoft SDK 6.0.1.5+**: Management platform SDK
|
||||
- **Windows Server 2016+** or **Windows 10/11**: Required for both SDKs
|
||||
- **Active GeViSoft System**: Configured with GeViScope instances
|
||||
- **Active GeViScope Instances**: One or more GSCServer instances with cameras and monitors
|
||||
|
||||
### Assumptions
|
||||
|
||||
- GeViSoft and GeViScope instances are installed, configured, and operational
|
||||
- Network connectivity exists between API server and all GeViScope/GeViSoft instances
|
||||
- Authentication credentials available for all instances
|
||||
- Sufficient storage for ring buffer recording
|
||||
- CrossSwitch commands execute at server level, viewer applications (GSCView) required for actual video display
|
||||
- Monitor IDs may not be unique across instances (scoped by instance ID in API)
|
||||
|
||||
### Out of Scope
|
||||
|
||||
- Direct camera hardware management (firmware, network config)
|
||||
- GSCView configuration and deployment
|
||||
- Custom video codec development
|
||||
- Mobile native SDKs (REST API only)
|
||||
- Video wall display management UI
|
||||
- Bi-directional audio communication
|
||||
- Custom analytics algorithm development
|
||||
|
||||
## Constraints
|
||||
|
||||
### Technical Constraints
|
||||
|
||||
- API must run on Windows platform due to SDK dependencies
|
||||
- All video operations use GeViScope's channel-based architecture
|
||||
- Event notifications limited to SDK-supported events
|
||||
- Recording capabilities bounded by ring buffer architecture
|
||||
- CrossSwitch routes video at server level, does NOT control physical displays (requires viewers)
|
||||
- Monitor enumeration may return more monitors than physically exist (SDK implementation detail)
|
||||
|
||||
### Performance Constraints
|
||||
|
||||
- Maximum concurrent streams limited by GeViScope SDK licenses and hardware
|
||||
- WebSocket connection limits determined by OS socket limits
|
||||
- Multi-instance operations may have higher latency than single-instance
|
||||
- CrossSwitch execution time depends on SDK response (typically <100ms)
|
||||
|
||||
### Security Constraints
|
||||
|
||||
- All API communication must use TLS 1.2+ in production
|
||||
- JWT tokens must have configurable expiration
|
||||
- Audit logging must be tamper-evident
|
||||
- Credentials for GeViSoft and GeViScope instances must be stored securely
|
||||
|
||||
## Risk Analysis
|
||||
|
||||
### High Impact Risks
|
||||
|
||||
1. **Multi-Instance Complexity**: Managing connections to multiple GeViScope instances increases failure modes
|
||||
- *Mitigation*: Circuit breaker per instance, independent health monitoring, graceful degradation
|
||||
|
||||
2. **CrossSwitch Verification**: Confirming routes are active requires viewer applications
|
||||
- *Mitigation*: Document viewer requirements, provide route tracking in database, API-level route verification
|
||||
|
||||
3. **GeViSoft/GeViScope Coordination**: Cross-system operations may have complex failure scenarios
|
||||
- *Mitigation*: Transaction-like patterns, compensating actions, clear error reporting
|
||||
|
||||
### Medium Impact Risks
|
||||
|
||||
4. **Instance Configuration Management**: Adding/removing instances requires careful config management
|
||||
- *Mitigation*: Configuration validation, instance health checks, hot-reload support
|
||||
|
||||
5. **SDK Version Compatibility**: Different GeViScope instances may run different SDK versions
|
||||
- *Mitigation*: Version detection, compatibility matrix, graceful feature detection
|
||||
|
||||
6. **Monitor ID Confusion**: Monitor IDs overlap across instances
|
||||
- *Mitigation*: Always scope monitors by instance ID in API, clear documentation
|
||||
|
||||
## Notes
|
||||
|
||||
This updated specification reflects the **unified architecture** supporting both GeViSoft management and multiple GeViScope instances. The API serves as a central control plane for the entire Geutebruck surveillance ecosystem.
|
||||
|
||||
**Key Architectural Decisions:**
|
||||
- Single API with two layers: GeViSoft (management) and GeViScope (operations)
|
||||
- Instance-based routing for GeViScope operations
|
||||
- CrossSwitch implemented with typed SDK actions for reliability
|
||||
- Monitor management reflects SDK's video output concept (logical channels, not physical displays)
|
||||
- Database tracks routes and provides audit trail
|
||||
|
||||
**Priority Sequencing:**
|
||||
- **P1** (Stories 1-6): MVP with auth, multi-instance, CrossSwitch, live video, PTZ, events
|
||||
- **P2** (Stories 7-10): GeViSoft integration, monitor management, recording, analytics
|
||||
- **P3** (Stories 11-12): Automation, advanced monitoring
|
||||
437
geutebruck-api/specs/001-surveillance-api/tasks-revised-mvp.md
Normal file
437
geutebruck-api/specs/001-surveillance-api/tasks-revised-mvp.md
Normal file
@@ -0,0 +1,437 @@
|
||||
# Tasks: Geutebruck Cross-Switching API (Revised MVP)
|
||||
|
||||
**Scope**: Cross-switching REST API with authentication, focusing on GeViSet-compatible configuration
|
||||
**MVP Goal**: Control GSCView viewers via cross-switching, no UI needed
|
||||
**Future Expansion**: GeViSet configuration management, action mapping, CSV import/export
|
||||
|
||||
---
|
||||
|
||||
## MVP User Stories
|
||||
|
||||
### US1: Authentication & Connection
|
||||
Connect to GeViServer, authenticate users, maintain sessions
|
||||
|
||||
### US2: Camera Discovery
|
||||
List all video inputs (cameras) with metadata
|
||||
|
||||
### US3: Monitor Discovery
|
||||
List all video outputs (GSCView viewers/monitors) with status
|
||||
|
||||
### US4: Cross-Switching Operations
|
||||
Route cameras to viewers, clear viewers, query routing state
|
||||
|
||||
---
|
||||
|
||||
## Revised Data Model (Simplified)
|
||||
|
||||
```
|
||||
User:
|
||||
- id, username, password_hash, role (viewer/operator/admin)
|
||||
|
||||
Camera:
|
||||
- id (channel), name, description, has_ptz, has_video_sensor, status
|
||||
|
||||
Monitor:
|
||||
- id (output channel), name, is_active, current_camera_id
|
||||
|
||||
CrossSwitchRoute:
|
||||
- id, camera_id, monitor_id, switched_at, switched_by_user_id
|
||||
|
||||
AuditLog:
|
||||
- id, user_id, action, target, timestamp, details
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation (Setup & Core Infrastructure)
|
||||
|
||||
**Purpose**: Project structure, dependencies, SDK bridge foundation
|
||||
|
||||
- [ ] T001 Create project structure (src/api, src/sdk-bridge, tests, docs, scripts)
|
||||
- [ ] T002 Create .gitignore for Python and C#
|
||||
- [ ] T003 Create requirements.txt with FastAPI, SQLAlchemy, Redis, grpcio, PyJWT, pytest
|
||||
- [ ] T004 Create SDK Bridge .csproj with .NET 8.0, Grpc.AspNetCore, GeViScope SDK reference
|
||||
- [ ] T005 Create .env.example with config variables (DB, Redis, JWT secret, GeViServer host/credentials)
|
||||
- [ ] T006 Create alembic.ini for database migrations
|
||||
- [ ] T007 [P] Create pyproject.toml with ruff, black, mypy configuration
|
||||
- [ ] T008 [P] Create scripts/setup_dev_environment.ps1 (install dependencies, setup DB, start services)
|
||||
- [ ] T009 [P] Create scripts/start_services.ps1 (start Redis, SDK Bridge, FastAPI)
|
||||
- [ ] T010 [P] Create docs/architecture.md documenting system design
|
||||
|
||||
**Checkpoint**: Project structure complete, dependencies defined
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: SDK Bridge Foundation (C# gRPC Service)
|
||||
|
||||
**Purpose**: Wrap GeViScope SDK with gRPC for Python consumption
|
||||
|
||||
### gRPC Protocol Definitions
|
||||
|
||||
- [ ] T011 Define common.proto (Status, Error, Timestamp, Empty messages)
|
||||
- [ ] T012 Define camera.proto (ListCamerasRequest/Response, CameraInfo with channel, name, has_ptz)
|
||||
- [ ] T013 Define monitor.proto (ListMonitorsRequest/Response, MonitorInfo with channel, name, current_camera)
|
||||
- [ ] T014 Define crossswitch.proto (CrossSwitchRequest, ClearMonitorRequest, GetRoutingStateRequest/Response)
|
||||
|
||||
### SDK Wrapper Implementation
|
||||
|
||||
- [ ] T015 Create GeViDatabaseWrapper.cs (Create, RegisterCallback, Connect, Disconnect, error handling)
|
||||
- [ ] T016 Implement connection lifecycle with retry logic (3 attempts, exponential backoff)
|
||||
- [ ] T017 Create StateQueryHandler.cs for GetFirst/GetNext enumeration pattern
|
||||
- [ ] T018 Implement EnumerateCameras() using CSQGetFirstVideoInput / CSQGetNextVideoInput
|
||||
- [ ] T019 Implement EnumerateMonitors() using CSQGetFirstVideoOutput / CSQGetNextVideoOutput
|
||||
- [ ] T020 Create ErrorTranslator.cs to map Windows error codes to gRPC status codes
|
||||
- [ ] T021 Create ActionDispatcher.cs for sending SDK actions (CrossSwitch, ClearVideoOutput)
|
||||
|
||||
### gRPC Service Implementation
|
||||
|
||||
- [ ] T022 Create CameraService.cs implementing camera.proto with ListCameras RPC
|
||||
- [ ] T023 Create MonitorService.cs implementing monitor.proto with ListMonitors RPC
|
||||
- [ ] T024 Create CrossSwitchService.cs with ExecuteCrossSwitch, ClearMonitor, GetRoutingState RPCs
|
||||
- [ ] T025 Create Program.cs gRPC server with Serilog logging, service registration
|
||||
- [ ] T026 Add configuration loading from appsettings.json (GeViServer host, port, credentials)
|
||||
|
||||
**Checkpoint**: SDK Bridge can connect to GeViServer, enumerate resources, execute cross-switch
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Python API Foundation
|
||||
|
||||
**Purpose**: FastAPI application structure, configuration, database setup
|
||||
|
||||
### Core Setup
|
||||
|
||||
- [ ] T027 Create main.py with FastAPI app, CORS middleware, exception handlers
|
||||
- [ ] T028 Create config.py loading settings from environment (Pydantic BaseSettings)
|
||||
- [ ] T029 Setup PostgreSQL connection with SQLAlchemy async engine in models/__init__.py
|
||||
- [ ] T030 Create initial Alembic migration for users and audit_logs tables
|
||||
- [ ] T031 Setup Redis client with connection pooling in clients/redis_client.py
|
||||
- [ ] T032 Create gRPC SDK Bridge client in clients/sdk_bridge_client.py with connection pooling
|
||||
- [ ] T033 [P] Create JWT utilities in utils/jwt_utils.py (encode, decode, verify)
|
||||
- [ ] T034 [P] Create error translation utilities in utils/error_translation.py (gRPC → HTTP status)
|
||||
- [ ] T035 Implement global error handler middleware in middleware/error_handler.py
|
||||
|
||||
### Database Models
|
||||
|
||||
- [ ] T036 [P] Create User model in models/user.py (id, username, password_hash, role, created_at)
|
||||
- [ ] T037 [P] Create AuditLog model in models/audit_log.py (id, user_id, action, target, timestamp)
|
||||
- [ ] T038 Run alembic upgrade head to create tables
|
||||
|
||||
**Checkpoint**: Python API can start, connect to DB/Redis, communicate with SDK Bridge via gRPC
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Authentication (User Story 1)
|
||||
|
||||
**Purpose**: JWT-based authentication with role-based access control
|
||||
|
||||
### Tests (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T039 [P] Write contract test for POST /api/v1/auth/login in tests/api/contract/test_auth.py (should FAIL)
|
||||
- [ ] T040 [P] Write contract test for POST /api/v1/auth/logout in tests/api/contract/test_auth.py (should FAIL)
|
||||
- [ ] T041 [P] Write unit test for AuthService in tests/api/unit/test_auth_service.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T042 [P] Create auth schemas in schemas/auth.py (LoginRequest, TokenResponse, UserInfo)
|
||||
- [ ] T043 Implement AuthService in services/auth_service.py (login, logout, validate_token, hash_password)
|
||||
- [ ] T044 Implement JWT token generation (access: 1hr, refresh: 7 days) with Redis session storage
|
||||
- [ ] T045 Implement authentication middleware in middleware/auth_middleware.py (verify JWT, extract user)
|
||||
- [ ] T046 Implement role checking decorator in utils/permissions.py (@require_role("operator"))
|
||||
- [ ] T047 Create auth router in routers/auth.py with POST /auth/login, POST /auth/logout
|
||||
- [ ] T048 Add audit logging for authentication attempts (success and failures)
|
||||
|
||||
**Verify**: Run tests T039-T041 - should now PASS
|
||||
|
||||
**Checkpoint**: Can login with credentials, receive JWT token, use token for authenticated requests
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Camera Discovery (User Story 2)
|
||||
|
||||
**Purpose**: List all cameras (video inputs) from GeViServer
|
||||
|
||||
### Tests (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T049 [P] Write contract test for GET /api/v1/cameras in tests/api/contract/test_cameras.py (should FAIL)
|
||||
- [ ] T050 [P] Write unit test for CameraService in tests/api/unit/test_camera_service.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T051 [P] Create camera schemas in schemas/camera.py (CameraInfo, CameraList)
|
||||
- [ ] T052 Implement CameraService in services/camera_service.py (list_cameras via gRPC to SDK Bridge)
|
||||
- [ ] T053 Create cameras router in routers/cameras.py with GET /cameras
|
||||
- [ ] T054 Add permission check: authenticated users only
|
||||
- [ ] T055 Add caching in Redis (cache camera list for 60 seconds to reduce SDK Bridge load)
|
||||
|
||||
**Verify**: Run tests T049-T050 - should now PASS
|
||||
|
||||
**Checkpoint**: GET /api/v1/cameras returns list of all cameras from GeViServer
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Monitor Discovery (User Story 3)
|
||||
|
||||
**Purpose**: List all monitors/viewers (video outputs) from GeViServer
|
||||
|
||||
### Tests (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T056 [P] Write contract test for GET /api/v1/monitors in tests/api/contract/test_monitors.py (should FAIL)
|
||||
- [ ] T057 [P] Write unit test for MonitorService in tests/api/unit/test_monitor_service.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T058 [P] Create monitor schemas in schemas/monitor.py (MonitorInfo, MonitorList)
|
||||
- [ ] T059 Implement MonitorService in services/monitor_service.py (list_monitors via gRPC to SDK Bridge)
|
||||
- [ ] T060 Create monitors router in routers/monitors.py with GET /monitors
|
||||
- [ ] T061 Add permission check: authenticated users only
|
||||
- [ ] T062 Add caching in Redis (cache monitor list for 60 seconds)
|
||||
|
||||
**Verify**: Run tests T056-T057 - should now PASS
|
||||
|
||||
**Checkpoint**: GET /api/v1/monitors returns list of all monitors/viewers from GeViServer
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Cross-Switching Operations (User Story 4)
|
||||
|
||||
**Purpose**: Execute cross-switch, clear monitors, query routing state
|
||||
|
||||
### Tests (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T063 [P] Write contract test for POST /api/v1/crossswitch in tests/api/contract/test_crossswitch.py (should FAIL)
|
||||
- [ ] T064 [P] Write contract test for DELETE /api/v1/monitors/{id} in tests/api/contract/test_crossswitch.py (should FAIL)
|
||||
- [ ] T065 [P] Write contract test for GET /api/v1/routing/state in tests/api/contract/test_crossswitch.py (should FAIL)
|
||||
- [ ] T066 [P] Write integration test for cross-switch workflow in tests/api/integration/test_crossswitch.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T067 [P] Create crossswitch schemas in schemas/crossswitch.py (CrossSwitchRequest, RoutingState, ClearMonitorRequest)
|
||||
- [ ] T068 Create CrossSwitchRoute model in models/crossswitch_route.py (id, camera_id, monitor_id, switched_at, user_id)
|
||||
- [ ] T069 Create Alembic migration for crossswitch_routes table
|
||||
- [ ] T070 Implement CrossSwitchService in services/crossswitch_service.py:
|
||||
- execute_crossswitch(camera_id, monitor_id, mode=0) → gRPC to SDK Bridge
|
||||
- clear_monitor(monitor_id) → gRPC ClearVideoOutput
|
||||
- get_routing_state() → query current routes
|
||||
- [ ] T071 Create crossswitch router in routers/crossswitch.py:
|
||||
- POST /crossswitch (requires operator or admin role)
|
||||
- DELETE /monitors/{id} (requires operator or admin role)
|
||||
- GET /routing/state (all authenticated users)
|
||||
- [ ] T072 Add audit logging for all cross-switch operations
|
||||
- [ ] T073 Add validation: camera_id and monitor_id must exist
|
||||
- [ ] T074 Store routing state in database for history/tracking
|
||||
|
||||
**Verify**: Run tests T063-T066 - should now PASS
|
||||
|
||||
**Checkpoint**: Can execute cross-switch via API, clear monitors, query current routing
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: MVP Polish & Documentation
|
||||
|
||||
**Purpose**: Complete MVP with documentation and deployment readiness
|
||||
|
||||
- [ ] T075 [P] Create API documentation in docs/api-usage.md with curl examples
|
||||
- [ ] T076 [P] Create deployment guide in docs/deployment.md (Windows Server setup, service installation)
|
||||
- [ ] T077 [P] Add Prometheus metrics endpoint at /metrics (request count, latency, active connections)
|
||||
- [ ] T078 [P] Create health check endpoint GET /health (SDK Bridge connectivity, DB, Redis status)
|
||||
- [ ] T079 [P] Add request logging with correlation IDs
|
||||
- [ ] T080 Create README.md with project overview, quick start, architecture diagram
|
||||
- [ ] T081 Update OpenAPI specification to include only MVP endpoints
|
||||
- [ ] T082 Create Postman collection for API testing
|
||||
- [ ] T083 Run full integration tests with actual GeViServer connection
|
||||
- [ ] T084 Security audit: Remove stack traces in production, sanitize logs
|
||||
|
||||
**Checkpoint**: MVP complete - REST API for cross-switching with authentication
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Future - GeViSet Configuration Management (Phase 2)
|
||||
|
||||
**Purpose**: GeViSet-like functionality via API (action mapping configuration)
|
||||
|
||||
**Note**: These tasks will be detailed after MVP is complete and working
|
||||
|
||||
### High-Level Tasks:
|
||||
|
||||
- [ ] T085 Research GeViSet configuration file format and action mapping structure
|
||||
- [ ] T086 Implement GET /api/v1/config/actions to retrieve action mappings from GeViServer
|
||||
- [ ] T087 Implement PUT /api/v1/config/actions to push action mappings to GeViServer
|
||||
- [ ] T088 Implement POST /api/v1/config/actions/export to export configuration to CSV
|
||||
- [ ] T089 Implement POST /api/v1/config/actions/import to import configuration from CSV
|
||||
- [ ] T090 Add validation for action mapping syntax and constraints
|
||||
- [ ] T091 Add versioning for configuration changes (track who changed what, when)
|
||||
- [ ] T092 Add backup/restore functionality for configurations
|
||||
|
||||
**Checkpoint**: GeViSet configuration management available via API
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
```
|
||||
Phase 1 (Setup)
|
||||
↓
|
||||
Phase 2 (SDK Bridge Foundation) ← BLOCKS all Python API work
|
||||
↓
|
||||
Phase 3 (Python API Foundation) ← BLOCKS all feature work
|
||||
↓
|
||||
Phase 4 (Authentication) ← BLOCKS all protected endpoints
|
||||
↓
|
||||
Phases 5, 6, 7 can proceed in parallel (after Phase 4)
|
||||
↓
|
||||
Phase 8 (Polish & Documentation)
|
||||
↓
|
||||
Phase 9 (Future - GeViSet config) ← After MVP validated
|
||||
```
|
||||
|
||||
### Critical Path (Sequential)
|
||||
|
||||
1. Setup → SDK Bridge → Python API → Authentication
|
||||
2. Then parallel: Camera Discovery + Monitor Discovery + Cross-Switching
|
||||
3. Then: Polish & Documentation
|
||||
4. Finally: GeViSet configuration (Phase 2)
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
- Phase 2: T020 (ErrorTranslator) parallel with T017-T019 (StateQuery implementation)
|
||||
- Phase 3: T033-T034, T036-T037 can run in parallel
|
||||
- Phase 4: T039-T041 tests can run in parallel
|
||||
- Phase 5-7: These entire phases can run in parallel after Phase 4 completes
|
||||
- Phase 8: T075-T082 can run in parallel
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### Week 1: Foundation
|
||||
- Days 1-2: Phase 1 (Setup)
|
||||
- Days 3-5: Phase 2 (SDK Bridge)
|
||||
|
||||
### Week 2: API Core
|
||||
- Days 1-3: Phase 3 (Python API Foundation)
|
||||
- Days 4-5: Phase 4 (Authentication)
|
||||
|
||||
### Week 3: Cross-Switching
|
||||
- Days 1-2: Phase 5 (Camera Discovery)
|
||||
- Days 2-3: Phase 6 (Monitor Discovery)
|
||||
- Days 4-5: Phase 7 (Cross-Switching Operations)
|
||||
|
||||
### Week 4: Polish & Validation
|
||||
- Days 1-3: Phase 8 (Polish, Documentation)
|
||||
- Days 4-5: Integration testing with real GeViServer, bug fixes
|
||||
|
||||
**MVP Delivery**: End of Week 4
|
||||
|
||||
### Week 5+: Phase 2 Features
|
||||
- GeViSet configuration management
|
||||
- Action mapping CRUD
|
||||
- CSV import/export
|
||||
|
||||
---
|
||||
|
||||
## Task Summary
|
||||
|
||||
**MVP Total**: 84 tasks
|
||||
|
||||
**By Phase**:
|
||||
- Phase 1 (Setup): 10 tasks
|
||||
- Phase 2 (SDK Bridge): 16 tasks
|
||||
- Phase 3 (API Foundation): 12 tasks
|
||||
- Phase 4 (Authentication): 10 tasks
|
||||
- Phase 5 (Camera Discovery): 7 tasks
|
||||
- Phase 6 (Monitor Discovery): 7 tasks
|
||||
- Phase 7 (Cross-Switching): 12 tasks
|
||||
- Phase 8 (Polish): 10 tasks
|
||||
|
||||
**Phase 2 (Future)**: 8+ tasks (detailed after MVP)
|
||||
|
||||
**Tests**: 12 test tasks (TDD approach)
|
||||
**Parallel Tasks**: 20+ tasks marked [P]
|
||||
|
||||
**Estimated Timeline**:
|
||||
- MVP: 3-4 weeks (1 developer, focused work)
|
||||
- Phase 2 (GeViSet config): +1-2 weeks
|
||||
|
||||
---
|
||||
|
||||
## MVP Endpoints Summary
|
||||
|
||||
```
|
||||
# Authentication
|
||||
POST /api/v1/auth/login # Get JWT token
|
||||
POST /api/v1/auth/logout # Invalidate token
|
||||
|
||||
# Cameras
|
||||
GET /api/v1/cameras # List all cameras
|
||||
|
||||
# Monitors
|
||||
GET /api/v1/monitors # List all monitors/viewers
|
||||
|
||||
# Cross-Switching
|
||||
POST /api/v1/crossswitch # Execute cross-switch
|
||||
Body: { camera_id: 7, monitor_id: 3, mode: 0 }
|
||||
|
||||
DELETE /api/v1/monitors/{id} # Clear monitor (stop video)
|
||||
|
||||
GET /api/v1/routing/state # Get current routing state
|
||||
|
||||
# System
|
||||
GET /api/v1/health # Health check (SDK Bridge, DB, Redis)
|
||||
GET /metrics # Prometheus metrics
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### TDD Approach
|
||||
1. Write contract test (should FAIL)
|
||||
2. Write unit tests (should FAIL)
|
||||
3. Implement feature
|
||||
4. Run tests (should PASS)
|
||||
5. Refactor if needed
|
||||
6. Commit
|
||||
|
||||
### Test Coverage Goal
|
||||
- Minimum 70% coverage for MVP
|
||||
- 100% coverage for authentication and cross-switching logic
|
||||
|
||||
### Manual Testing
|
||||
- Test with Postman collection
|
||||
- Test with curl commands
|
||||
- Integration test with actual GeViServer
|
||||
|
||||
---
|
||||
|
||||
**Generated**: 2025-12-08
|
||||
**Updated**: 2025-12-16 (Configuration Management implemented)
|
||||
**Scope**: Cross-switching MVP with authentication + GeViSet configuration management ✅
|
||||
**Architecture**: Python FastAPI + C# gRPC Bridge + GeViScope SDK
|
||||
|
||||
---
|
||||
|
||||
## UPDATE: Configuration Management (2025-12-16) ✅ COMPLETED
|
||||
|
||||
**Status**: Phase 9 (GeViSet Configuration Management) has been implemented ahead of schedule
|
||||
|
||||
**Implemented Features**:
|
||||
- ✅ G-Core Server CRUD operations (CREATE, READ, DELETE working; UPDATE has known bug)
|
||||
- ✅ Action Mapping CRUD operations (all CRUD operations working)
|
||||
- ✅ SetupClient integration for configuration file operations
|
||||
- ✅ Configuration tree parsing and navigation
|
||||
- ✅ Critical bug fixes (cascade deletion prevention)
|
||||
|
||||
**API Endpoints Added**:
|
||||
- `GET/POST/PUT/DELETE /api/v1/configuration/servers` - G-Core server management
|
||||
- `GET/POST/PUT/DELETE /api/v1/configuration/action-mappings` - Action mapping management
|
||||
|
||||
**Documentation**:
|
||||
- [SERVER_CRUD_IMPLEMENTATION.md](../../SERVER_CRUD_IMPLEMENTATION.md)
|
||||
- [CRITICAL_BUG_FIX_DELETE.md](../../CRITICAL_BUG_FIX_DELETE.md)
|
||||
|
||||
See Phase 9 section below for original planned tasks.
|
||||
|
||||
---
|
||||
771
geutebruck-api/specs/001-surveillance-api/tasks.md
Normal file
771
geutebruck-api/specs/001-surveillance-api/tasks.md
Normal file
@@ -0,0 +1,771 @@
|
||||
# Tasks: Geutebruck Surveillance API
|
||||
|
||||
**Input**: Design documents from `/specs/001-surveillance-api/`
|
||||
**Prerequisites**: plan.md ✅, spec.md ✅, research.md ✅, data-model.md ✅, contracts/openapi.yaml ✅
|
||||
|
||||
**Tests**: TDD approach enforced - all tests MUST be written first and FAIL before implementation begins.
|
||||
|
||||
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
||||
|
||||
---
|
||||
|
||||
## Format: `[ID] [P?] [Story] Description`
|
||||
|
||||
- **[P]**: Can run in parallel (different files, no dependencies)
|
||||
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
||||
- Include exact file paths in descriptions
|
||||
|
||||
---
|
||||
|
||||
## Path Conventions
|
||||
|
||||
This project uses **web application structure**:
|
||||
- **Python API**: `src/api/` (FastAPI application)
|
||||
- **C# SDK Bridge**: `src/sdk-bridge/` (gRPC service)
|
||||
- **Tests**: `tests/api/` (Python), `tests/sdk-bridge/` (C#)
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Setup (Shared Infrastructure)
|
||||
|
||||
**Purpose**: Project initialization and basic structure
|
||||
|
||||
- [ ] T001 Create Python project structure: src/api/ with subdirs (models/, schemas/, routers/, services/, clients/, middleware/, websocket/, utils/, migrations/)
|
||||
- [ ] T002 Create C# SDK Bridge structure: src/sdk-bridge/ with GeViScopeBridge.sln, Services/, SDK/, Protos/
|
||||
- [ ] T003 Create test structure: tests/api/ (unit/, integration/, contract/) and tests/sdk-bridge/ (Unit/, Integration/)
|
||||
- [ ] T004 [P] Initialize Python dependencies in requirements.txt (FastAPI, Uvicorn, SQLAlchemy, Redis, grpcio, PyJWT, pytest)
|
||||
- [ ] T005 [P] Initialize C# project with .NET 8.0 gRPC and .NET Framework 4.8 SDK dependencies
|
||||
- [ ] T006 [P] Configure Python linting/formatting (ruff, black, mypy) in pyproject.toml
|
||||
- [ ] T007 [P] Create .env.example with all required environment variables
|
||||
- [ ] T008 [P] Create scripts/setup_dev_environment.ps1 for automated development environment setup
|
||||
- [ ] T009 [P] Create scripts/start_services.ps1 to start Redis, SDK Bridge, and API
|
||||
- [ ] T010 [P] Setup Alembic for database migrations in src/api/migrations/
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational (Blocking Prerequisites)
|
||||
|
||||
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
|
||||
|
||||
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
||||
|
||||
### C# SDK Bridge Foundation
|
||||
|
||||
- [ ] T011 Define gRPC protocol buffer for common types in src/sdk-bridge/Protos/common.proto (Status, Error, Timestamp)
|
||||
- [ ] T012 Create GeViDatabaseWrapper.cs in src/sdk-bridge/SDK/ (wraps GeViDatabase connection lifecycle)
|
||||
- [ ] T013 Implement connection management: Create → RegisterCallback → Connect pattern with retry logic
|
||||
- [ ] T014 [P] Create StateQueryHandler.cs for GetFirst/GetNext enumeration pattern
|
||||
- [ ] T015 [P] Create DatabaseQueryHandler.cs for historical query sessions
|
||||
- [ ] T016 Implement error translation from Windows error codes to gRPC status codes in src/sdk-bridge/Utils/ErrorTranslator.cs
|
||||
- [ ] T017 Setup gRPC server in src/sdk-bridge/Program.cs with service registration
|
||||
|
||||
### Python API Foundation
|
||||
|
||||
- [ ] T018 Create FastAPI app initialization in src/api/main.py with CORS, middleware registration
|
||||
- [ ] T019 [P] Create configuration management in src/api/config.py loading from environment variables
|
||||
- [ ] T020 [P] Setup PostgreSQL connection with SQLAlchemy in src/api/models/__init__.py
|
||||
- [ ] T021 [P] Setup Redis client with connection pooling in src/api/clients/redis_client.py
|
||||
- [ ] T022 Create gRPC SDK Bridge client in src/api/clients/sdk_bridge_client.py with connection pooling
|
||||
- [ ] T023 [P] Implement JWT utilities in src/api/utils/jwt_utils.py (encode, decode, verify)
|
||||
- [ ] T024 [P] Create error translation utilities in src/api/utils/error_translation.py (SDK errors → HTTP status)
|
||||
- [ ] T025 Implement global error handler middleware in src/api/middleware/error_handler.py
|
||||
- [ ] T026 [P] Create base Pydantic schemas in src/api/schemas/__init__.py (ErrorResponse, SuccessResponse)
|
||||
|
||||
### Database & Testing Infrastructure
|
||||
|
||||
- [ ] T027 Create initial Alembic migration for database schema (users, audit_logs tables)
|
||||
- [ ] T028 [P] Setup pytest configuration in tests/api/conftest.py with fixtures (test_db, test_redis, test_client)
|
||||
- [ ] T029 [P] Setup xUnit test infrastructure in tests/sdk-bridge/ with test SDK connection
|
||||
|
||||
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Secure API Access (Priority: P1) 🎯 MVP
|
||||
|
||||
**Goal**: Implement JWT-based authentication with role-based access control (viewer, operator, administrator)
|
||||
|
||||
**Independent Test**: Can authenticate with valid credentials to receive JWT token, access protected endpoints with token, and receive 401 for invalid/expired tokens
|
||||
|
||||
### Tests for User Story 1 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T030 [P] [US1] Write contract test for POST /api/v1/auth/login in tests/api/contract/test_auth_contract.py (should FAIL)
|
||||
- [ ] T031 [P] [US1] Write contract test for POST /api/v1/auth/refresh in tests/api/contract/test_auth_contract.py (should FAIL)
|
||||
- [ ] T032 [P] [US1] Write contract test for POST /api/v1/auth/logout in tests/api/contract/test_auth_contract.py (should FAIL)
|
||||
- [ ] T033 [P] [US1] Write integration test for authentication flow in tests/api/integration/test_auth_flow.py (should FAIL)
|
||||
- [ ] T034 [P] [US1] Write unit test for AuthService in tests/api/unit/test_auth_service.py (should FAIL)
|
||||
|
||||
### Implementation for User Story 1
|
||||
|
||||
- [ ] T035 [P] [US1] Create User model in src/api/models/user.py (id, username, password_hash, role, permissions, created_at, updated_at)
|
||||
- [ ] T036 [P] [US1] Create AuditLog model in src/api/models/audit_log.py (id, user_id, action, target, outcome, timestamp, details)
|
||||
- [ ] T037 [US1] Create Alembic migration for User and AuditLog tables
|
||||
- [ ] T038 [P] [US1] Create auth request/response schemas in src/api/schemas/auth.py (LoginRequest, TokenResponse, RefreshRequest)
|
||||
- [ ] T039 [US1] Implement AuthService in src/api/services/auth_service.py (login, refresh, logout, validate_token)
|
||||
- [ ] T040 [US1] Implement password hashing with bcrypt in AuthService
|
||||
- [ ] T041 [US1] Implement JWT token generation (access: 1hr, refresh: 7 days) with Redis session storage
|
||||
- [ ] T042 [US1] Implement authentication middleware in src/api/middleware/auth_middleware.py (verify JWT, extract user)
|
||||
- [ ] T043 [US1] Implement rate limiting middleware for auth endpoints in src/api/middleware/rate_limiter.py (5 attempts/min)
|
||||
- [ ] T044 [US1] Create auth router in src/api/routers/auth.py with login, refresh, logout endpoints
|
||||
- [ ] T045 [US1] Implement audit logging for authentication attempts (success and failures)
|
||||
- [ ] T046 [US1] Add role-based permission checking utilities in src/api/utils/permissions.py
|
||||
|
||||
**Verify**: Run tests T030-T034 - they should now PASS
|
||||
|
||||
**Checkpoint**: Authentication system complete - can login, get tokens, access protected endpoints
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - Live Video Stream Access (Priority: P1)
|
||||
|
||||
**Goal**: Enable users to view live video streams from surveillance cameras with <2s initialization time
|
||||
|
||||
**Independent Test**: Authenticate, request stream URL for camera, receive RTSP URL with token, play stream in video player
|
||||
|
||||
### gRPC Protocol Definitions
|
||||
|
||||
- [ ] T047 [US2] Define camera.proto in src/sdk-bridge/Protos/ (ListCamerasRequest/Response, GetCameraRequest/Response, CameraInfo)
|
||||
- [ ] T048 [US2] Define stream.proto in src/sdk-bridge/Protos/ (StartStreamRequest/Response, StopStreamRequest/Response, StreamInfo)
|
||||
|
||||
### Tests for User Story 2 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T049 [P] [US2] Write contract test for GET /api/v1/cameras in tests/api/contract/test_cameras_contract.py (should FAIL)
|
||||
- [ ] T050 [P] [US2] Write contract test for GET /api/v1/cameras/{id} in tests/api/contract/test_cameras_contract.py (should FAIL)
|
||||
- [ ] T051 [P] [US2] Write contract test for POST /api/v1/cameras/{id}/stream in tests/api/contract/test_cameras_contract.py (should FAIL)
|
||||
- [ ] T052 [P] [US2] Write contract test for DELETE /api/v1/cameras/{id}/stream/{stream_id} in tests/api/contract/test_cameras_contract.py (should FAIL)
|
||||
- [ ] T053 [P] [US2] Write integration test for stream lifecycle in tests/api/integration/test_stream_lifecycle.py (should FAIL)
|
||||
- [ ] T054 [P] [US2] Write unit test for CameraService in tests/api/unit/test_camera_service.py (should FAIL)
|
||||
- [ ] T055 [P] [US2] Write C# unit test for CameraService gRPC in tests/sdk-bridge/Unit/CameraServiceTests.cs (should FAIL)
|
||||
|
||||
### Implementation - SDK Bridge (C#)
|
||||
|
||||
- [ ] T056 [US2] Implement CameraService.cs in src/sdk-bridge/Services/ with ListCameras (GetFirstVideoInput/GetNextVideoInput pattern)
|
||||
- [ ] T057 [US2] Implement GetCameraDetails in CameraService.cs (query video input info: channel, name, capabilities)
|
||||
- [ ] T058 [US2] Implement GetCameraStatus in CameraService.cs (online/offline detection)
|
||||
- [ ] T059 [US2] Implement StreamService.cs in src/sdk-bridge/Services/ with StartStream method
|
||||
- [ ] T060 [US2] Generate RTSP URL with token in StreamService.cs (format: rtsp://host:port/stream/{id}?token={jwt})
|
||||
- [ ] T061 [US2] Implement StopStream method in StreamService.cs
|
||||
- [ ] T062 [US2] Track active streams with channel mapping in StreamService.cs
|
||||
|
||||
### Implementation - Python API
|
||||
|
||||
- [ ] T063 [P] [US2] Create Camera model in src/api/models/camera.py (id, channel, name, description, status, capabilities)
|
||||
- [ ] T064 [P] [US2] Create Stream model in src/api/models/stream.py (id, camera_id, user_id, url, started_at, expires_at)
|
||||
- [ ] T065 [US2] Create Alembic migration for Camera and Stream tables
|
||||
- [ ] T066 [P] [US2] Create camera schemas in src/api/schemas/camera.py (CameraInfo, CameraList, CameraCapabilities)
|
||||
- [ ] T067 [P] [US2] Create stream schemas in src/api/schemas/stream.py (StartStreamRequest, StreamResponse)
|
||||
- [ ] T068 [US2] Implement CameraService in src/api/services/camera_service.py (list, get_details, sync from SDK bridge)
|
||||
- [ ] T069 [US2] Implement StreamService in src/api/services/stream_service.py (start, stop, track active streams)
|
||||
- [ ] T070 [US2] Implement token generation for stream URLs (15min expiration)
|
||||
- [ ] T071 [US2] Create cameras router in src/api/routers/cameras.py with GET /cameras, GET /cameras/{id}
|
||||
- [ ] T072 [US2] Implement stream endpoints: POST /cameras/{id}/stream, DELETE /cameras/{id}/stream/{stream_id}
|
||||
- [ ] T073 [US2] Add permission checks: users can only access cameras they have permission for (403 if unauthorized)
|
||||
- [ ] T074 [US2] Implement camera offline error handling (clear error message when camera unavailable)
|
||||
|
||||
**Verify**: Run tests T049-T055 - they should now PASS
|
||||
|
||||
**Checkpoint**: Live streaming functional - can list cameras, start/stop streams, play video
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: User Story 3 - Camera PTZ Control (Priority: P1)
|
||||
|
||||
**Goal**: Enable remote pan-tilt-zoom control for PTZ-capable cameras with <500ms response time
|
||||
|
||||
**Independent Test**: Send PTZ command (pan left/right, tilt up/down, zoom in/out) to PTZ camera, verify movement occurs
|
||||
|
||||
### gRPC Protocol Definitions
|
||||
|
||||
- [ ] T075 [US3] Define ptz.proto in src/sdk-bridge/Protos/ (PTZMoveRequest, PTZPresetRequest, PTZResponse)
|
||||
|
||||
### Tests for User Story 3 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T076 [P] [US3] Write contract test for POST /api/v1/cameras/{id}/ptz in tests/api/contract/test_ptz_contract.py (should FAIL)
|
||||
- [ ] T077 [P] [US3] Write integration test for PTZ control in tests/api/integration/test_ptz_control.py (should FAIL)
|
||||
- [ ] T078 [P] [US3] Write unit test for PTZService in tests/api/unit/test_ptz_service.py (should FAIL)
|
||||
- [ ] T079 [P] [US3] Write C# unit test for PTZService gRPC in tests/sdk-bridge/Unit/PTZServiceTests.cs (should FAIL)
|
||||
|
||||
### Implementation - SDK Bridge (C#)
|
||||
|
||||
- [ ] T080 [US3] Implement PTZService.cs in src/sdk-bridge/Services/ with MoveCamera method (pan, tilt, zoom, speed)
|
||||
- [ ] T081 [US3] Implement SetPreset and GotoPreset methods in PTZService.cs
|
||||
- [ ] T082 [US3] Implement StopMovement method in PTZService.cs
|
||||
- [ ] T083 [US3] Add PTZ command queuing for concurrent control conflict resolution
|
||||
|
||||
### Implementation - Python API
|
||||
|
||||
- [ ] T084 [P] [US3] Create PTZ schemas in src/api/schemas/ptz.py (PTZMoveCommand, PTZPresetCommand, PTZResponse)
|
||||
- [ ] T085 [US3] Implement PTZService in src/api/services/ptz_service.py (move, set_preset, goto_preset, stop)
|
||||
- [ ] T086 [US3] Add PTZ endpoints to cameras router: POST /cameras/{id}/ptz
|
||||
- [ ] T087 [US3] Implement PTZ capability validation (return error if camera doesn't support PTZ)
|
||||
- [ ] T088 [US3] Implement operator role requirement for PTZ control (viewers can't control PTZ)
|
||||
- [ ] T089 [US3] Add audit logging for all PTZ commands
|
||||
|
||||
**Verify**: Run tests T076-T079 - they should now PASS
|
||||
|
||||
**Checkpoint**: PTZ control functional - can move cameras, use presets, operators have control
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: User Story 4 - Real-time Event Notifications (Priority: P1)
|
||||
|
||||
**Goal**: Deliver real-time surveillance event notifications via WebSocket with <100ms latency to 1000+ concurrent clients
|
||||
|
||||
**Independent Test**: Connect to WebSocket, subscribe to event types, trigger test alarm, receive notification within 100ms
|
||||
|
||||
### gRPC Protocol Definitions
|
||||
|
||||
- [ ] T090 [US4] Define event.proto in src/sdk-bridge/Protos/ (SubscribeEventsRequest, EventNotification with server streaming)
|
||||
|
||||
### Tests for User Story 4 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T091 [P] [US4] Write contract test for WebSocket /api/v1/events/stream in tests/api/contract/test_events_contract.py (should FAIL)
|
||||
- [ ] T092 [P] [US4] Write contract test for GET /api/v1/events in tests/api/contract/test_events_contract.py (should FAIL)
|
||||
- [ ] T093 [P] [US4] Write integration test for event notification flow in tests/api/integration/test_event_notifications.py (should FAIL)
|
||||
- [ ] T094 [P] [US4] Write unit test for EventService in tests/api/unit/test_event_service.py (should FAIL)
|
||||
- [ ] T095 [P] [US4] Write C# unit test for EventService gRPC in tests/sdk-bridge/Unit/EventServiceTests.cs (should FAIL)
|
||||
|
||||
### Implementation - SDK Bridge (C#)
|
||||
|
||||
- [ ] T096 [US4] Implement EventService.cs in src/sdk-bridge/Services/ with SubscribeEvents (server streaming)
|
||||
- [ ] T097 [US4] Register SDK event callbacks for motion, alarms, analytics, system events
|
||||
- [ ] T098 [US4] Map SDK events to gRPC EventNotification messages
|
||||
- [ ] T099 [US4] Implement event filtering by type and camera channel
|
||||
|
||||
### Implementation - Python API
|
||||
|
||||
- [ ] T100 [P] [US4] Create Event model in src/api/models/event.py (id, type, camera_id, timestamp, severity, data)
|
||||
- [ ] T101 [US4] Create Alembic migration for Event table
|
||||
- [ ] T102 [P] [US4] Create event schemas in src/api/schemas/event.py (EventNotification, EventQuery, EventFilter)
|
||||
- [ ] T103 [US4] Implement WebSocket connection manager in src/api/websocket/connection_manager.py (add, remove, broadcast)
|
||||
- [ ] T104 [US4] Implement Redis pub/sub event broadcaster in src/api/websocket/event_broadcaster.py (subscribe to SDK bridge events)
|
||||
- [ ] T105 [US4] Create background task to consume SDK bridge event stream and publish to Redis
|
||||
- [ ] T106 [US4] Implement WebSocket endpoint in src/api/routers/events.py: WS /events/stream
|
||||
- [ ] T107 [US4] Implement event subscription management (subscribe, unsubscribe to event types)
|
||||
- [ ] T108 [US4] Implement client reconnection handling with missed event recovery
|
||||
- [ ] T109 [US4] Implement EventService in src/api/services/event_service.py (query historical events)
|
||||
- [ ] T110 [US4] Create REST endpoint: GET /events (query with filters: camera, type, time range)
|
||||
- [ ] T111 [US4] Implement permission filtering (users only receive events for authorized cameras)
|
||||
|
||||
**Verify**: Run tests T091-T095 - they should now PASS
|
||||
|
||||
**Checkpoint**: Event notifications working - WebSocket delivers real-time alerts, query historical events
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: User Story 5 - Recording Management (Priority: P2)
|
||||
|
||||
**Goal**: Manage video recording settings and query recorded footage for investigations
|
||||
|
||||
**Independent Test**: Start recording on camera, query recordings by time range, receive list with download URLs
|
||||
|
||||
### gRPC Protocol Definitions
|
||||
|
||||
- [ ] T112 [US5] Define recording.proto in src/sdk-bridge/Protos/ (QueryRecordingsRequest, StartRecordingRequest, RecordingInfo)
|
||||
|
||||
### Tests for User Story 5 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T113 [P] [US5] Write contract test for GET /api/v1/recordings in tests/api/contract/test_recordings_contract.py (should FAIL)
|
||||
- [ ] T114 [P] [US5] Write contract test for POST /api/v1/recordings/{id}/export in tests/api/contract/test_recordings_contract.py (should FAIL)
|
||||
- [ ] T115 [P] [US5] Write integration test for recording management in tests/api/integration/test_recording_management.py (should FAIL)
|
||||
- [ ] T116 [P] [US5] Write unit test for RecordingService in tests/api/unit/test_recording_service.py (should FAIL)
|
||||
- [ ] T117 [P] [US5] Write C# unit test for RecordingService gRPC in tests/sdk-bridge/Unit/RecordingServiceTests.cs (should FAIL)
|
||||
|
||||
### Implementation - SDK Bridge (C#)
|
||||
|
||||
- [ ] T118 [US5] Implement RecordingService.cs in src/sdk-bridge/Services/ with QueryRecordings (database query with time range)
|
||||
- [ ] T119 [US5] Implement StartRecording and StopRecording methods
|
||||
- [ ] T120 [US5] Implement GetRecordingCapacity method (ring buffer metrics)
|
||||
- [ ] T121 [US5] Query recording segments using CDBQCreateActionQuery pattern
|
||||
|
||||
### Implementation - Python API
|
||||
|
||||
- [ ] T122 [P] [US5] Create Recording model in src/api/models/recording.py (id, camera_id, start_time, end_time, size_bytes, trigger_type)
|
||||
- [ ] T123 [US5] Create Alembic migration for Recording table
|
||||
- [ ] T124 [P] [US5] Create recording schemas in src/api/schemas/recording.py (RecordingQuery, RecordingInfo, ExportRequest)
|
||||
- [ ] T125 [US5] Implement RecordingService in src/api/services/recording_service.py (query, start, stop, export)
|
||||
- [ ] T126 [US5] Create recordings router in src/api/routers/recordings.py: GET /recordings, POST /recordings/{id}/export
|
||||
- [ ] T127 [US5] Implement recording query with filters (camera, time range, event type)
|
||||
- [ ] T128 [US5] Implement export job creation (async job with progress tracking)
|
||||
- [ ] T129 [US5] Implement ring buffer capacity monitoring and warnings (alert at 90%)
|
||||
- [ ] T130 [US5] Add administrator role requirement for starting/stopping recording
|
||||
|
||||
**Verify**: Run tests T113-T117 - they should now PASS
|
||||
|
||||
**Checkpoint**: Recording management functional - query, export, capacity monitoring
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: User Story 6 - Video Analytics Configuration (Priority: P2)
|
||||
|
||||
**Goal**: Configure video content analysis features (VMD, object tracking, perimeter protection)
|
||||
|
||||
**Independent Test**: Configure motion detection zone on camera, trigger motion, verify analytics event generated
|
||||
|
||||
### gRPC Protocol Definitions
|
||||
|
||||
- [ ] T131 [US6] Define analytics.proto in src/sdk-bridge/Protos/ (ConfigureAnalyticsRequest, AnalyticsConfig with union types for VMD/NPR/OBTRACK/G-Tect)
|
||||
|
||||
### Tests for User Story 6 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T132 [P] [US6] Write contract test for GET /api/v1/analytics/{camera_id} in tests/api/contract/test_analytics_contract.py (should FAIL)
|
||||
- [ ] T133 [P] [US6] Write contract test for POST /api/v1/analytics/{camera_id} in tests/api/contract/test_analytics_contract.py (should FAIL)
|
||||
- [ ] T134 [P] [US6] Write integration test for analytics configuration in tests/api/integration/test_analytics_config.py (should FAIL)
|
||||
- [ ] T135 [P] [US6] Write unit test for AnalyticsService in tests/api/unit/test_analytics_service.py (should FAIL)
|
||||
- [ ] T136 [P] [US6] Write C# unit test for AnalyticsService gRPC in tests/sdk-bridge/Unit/AnalyticsServiceTests.cs (should FAIL)
|
||||
|
||||
### Implementation - SDK Bridge (C#)
|
||||
|
||||
- [ ] T137 [US6] Implement AnalyticsService.cs in src/sdk-bridge/Services/ with ConfigureAnalytics method
|
||||
- [ ] T138 [US6] Implement GetAnalyticsConfig method (query current analytics settings)
|
||||
- [ ] T139 [US6] Map analytics types to SDK sensor types (VMD, NPR, OBTRACK, G-Tect, CPA)
|
||||
- [ ] T140 [US6] Implement region/zone configuration for analytics
|
||||
|
||||
### Implementation - Python API
|
||||
|
||||
- [ ] T141 [P] [US6] Create AnalyticsConfig model in src/api/models/analytics_config.py (id, camera_id, type, enabled, configuration JSON)
|
||||
- [ ] T142 [US6] Create Alembic migration for AnalyticsConfig table
|
||||
- [ ] T143 [P] [US6] Create analytics schemas in src/api/schemas/analytics.py (AnalyticsConfigRequest, VMDConfig, NPRConfig, OBTRACKConfig)
|
||||
- [ ] T144 [US6] Implement AnalyticsService in src/api/services/analytics_service.py (configure, get_config, validate)
|
||||
- [ ] T145 [US6] Create analytics router in src/api/routers/analytics.py: GET/POST /analytics/{camera_id}
|
||||
- [ ] T146 [US6] Implement analytics capability validation (return error if camera doesn't support requested analytics)
|
||||
- [ ] T147 [US6] Add administrator role requirement for analytics configuration
|
||||
- [ ] T148 [US6] Implement schedule support for analytics (enable/disable by time/day)
|
||||
|
||||
**Verify**: Run tests T132-T136 - they should now PASS
|
||||
|
||||
**Checkpoint**: Analytics configuration functional - configure VMD, NPR, OBTRACK, receive analytics events
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: User Story 7 - Multi-Camera Management (Priority: P2)
|
||||
|
||||
**Goal**: View and manage multiple cameras simultaneously with location grouping
|
||||
|
||||
**Independent Test**: Request camera list, verify all authorized cameras returned with metadata, group by location
|
||||
|
||||
### Tests for User Story 7 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T149 [P] [US7] Write contract test for camera list with filtering/pagination in tests/api/contract/test_camera_list_contract.py (should FAIL)
|
||||
- [ ] T150 [P] [US7] Write integration test for multi-camera operations in tests/api/integration/test_multi_camera.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T151 [P] [US7] Add location field to Camera model (update migration)
|
||||
- [ ] T152 [US7] Implement camera list filtering by location, status, capabilities in CameraService
|
||||
- [ ] T153 [US7] Implement pagination for camera list (page, page_size parameters)
|
||||
- [ ] T154 [US7] Update GET /cameras endpoint with query parameters (location, status, capabilities, page, page_size)
|
||||
- [ ] T155 [US7] Implement camera grouping by location in response
|
||||
- [ ] T156 [US7] Implement concurrent stream limit tracking (warn if approaching limit)
|
||||
- [ ] T157 [US7] Add camera status change notifications via WebSocket (camera goes offline → event)
|
||||
|
||||
**Verify**: Run tests T149-T150 - they should now PASS
|
||||
|
||||
**Checkpoint**: Multi-camera management functional - filtering, grouping, concurrent access
|
||||
|
||||
---
|
||||
|
||||
## Phase 10: User Story 8 - License Plate Recognition Integration (Priority: P3)
|
||||
|
||||
**Goal**: Receive automatic license plate recognition events with watchlist matching
|
||||
|
||||
**Independent Test**: Configure NPR zone, drive test vehicle through zone, receive NPR event with plate number
|
||||
|
||||
### Tests for User Story 8 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T158 [P] [US8] Write integration test for NPR events in tests/api/integration/test_npr_events.py (should FAIL)
|
||||
- [ ] T159 [P] [US8] Write unit test for NPR watchlist matching in tests/api/unit/test_npr_service.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T160 [P] [US8] Create NPREvent model extending Event in src/api/models/event.py (plate_number, country_code, confidence, image_url)
|
||||
- [ ] T161 [US8] Create Alembic migration for NPREvent table
|
||||
- [ ] T162 [P] [US8] Create Watchlist model in src/api/models/watchlist.py (id, plate_number, alert_level, notes)
|
||||
- [ ] T163 [US8] Create Alembic migration for Watchlist table
|
||||
- [ ] T164 [P] [US8] Create NPR schemas in src/api/schemas/npr.py (NPREventData, WatchlistEntry)
|
||||
- [ ] T165 [US8] Implement NPR event handling in EventService (parse NPR data from SDK)
|
||||
- [ ] T166 [US8] Implement watchlist matching service (check incoming plates against watchlist)
|
||||
- [ ] T167 [US8] Implement high-priority alerts for watchlist matches
|
||||
- [ ] T168 [US8] Add NPR-specific filtering to GET /events endpoint
|
||||
- [ ] T169 [US8] Create watchlist management endpoints: GET/POST/DELETE /api/v1/watchlist
|
||||
|
||||
**Verify**: Run tests T158-T159 - they should now PASS
|
||||
|
||||
**Checkpoint**: NPR integration functional - receive plate events, watchlist matching, alerts
|
||||
|
||||
---
|
||||
|
||||
## Phase 11: User Story 9 - Video Export and Backup (Priority: P3)
|
||||
|
||||
**Goal**: Export specific video segments for evidence with progress tracking
|
||||
|
||||
**Independent Test**: Request export of 10-minute segment, poll job status, download exported file
|
||||
|
||||
### Tests for User Story 9 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T170 [P] [US9] Write contract test for export job in tests/api/contract/test_export_contract.py (should FAIL)
|
||||
- [ ] T171 [P] [US9] Write integration test for export workflow in tests/api/integration/test_export_workflow.py (should FAIL)
|
||||
- [ ] T172 [P] [US9] Write unit test for ExportService in tests/api/unit/test_export_service.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T173 [P] [US9] Create ExportJob model in src/api/models/export_job.py (id, camera_id, start_time, end_time, status, progress, file_path)
|
||||
- [ ] T174 [US9] Create Alembic migration for ExportJob table
|
||||
- [ ] T175 [P] [US9] Create export schemas in src/api/schemas/export.py (ExportRequest, ExportJobStatus)
|
||||
- [ ] T176 [US9] Implement ExportService in src/api/services/export_service.py (create_job, get_status, download)
|
||||
- [ ] T177 [US9] Implement background worker for export processing (query recordings, concatenate, encode to MP4)
|
||||
- [ ] T178 [US9] Implement progress tracking and updates (percentage complete, ETA)
|
||||
- [ ] T179 [US9] Update POST /recordings/{id}/export to create export job and return job ID
|
||||
- [ ] T180 [US9] Create GET /api/v1/exports/{job_id} endpoint for job status polling
|
||||
- [ ] T181 [US9] Create GET /api/v1/exports/{job_id}/download endpoint for file download
|
||||
- [ ] T182 [US9] Implement cleanup of old export files (auto-delete after 24 hours)
|
||||
- [ ] T183 [US9] Add timestamp watermarking to exported video
|
||||
|
||||
**Verify**: Run tests T170-T172 - they should now PASS
|
||||
|
||||
**Checkpoint**: Video export functional - create jobs, track progress, download files
|
||||
|
||||
---
|
||||
|
||||
## Phase 12: User Story 10 - System Health Monitoring (Priority: P3)
|
||||
|
||||
**Goal**: Monitor API and surveillance system health with proactive alerts
|
||||
|
||||
**Independent Test**: Query health endpoint, verify SDK connectivity status, simulate component failure
|
||||
|
||||
### Tests for User Story 10 (TDD - Write FIRST, Ensure FAIL)
|
||||
|
||||
- [ ] T184 [P] [US10] Write contract test for GET /api/v1/health in tests/api/contract/test_health_contract.py (should FAIL)
|
||||
- [ ] T185 [P] [US10] Write contract test for GET /api/v1/status in tests/api/contract/test_health_contract.py (should FAIL)
|
||||
- [ ] T186 [P] [US10] Write integration test for health monitoring in tests/api/integration/test_health_monitoring.py (should FAIL)
|
||||
|
||||
### Implementation
|
||||
|
||||
- [ ] T187 [P] [US10] Create health schemas in src/api/schemas/health.py (HealthResponse, SystemStatus, ComponentHealth)
|
||||
- [ ] T188 [US10] Implement HealthService in src/api/services/health_service.py (check all components)
|
||||
- [ ] T189 [US10] Implement SDK Bridge health check (gRPC connectivity test)
|
||||
- [ ] T190 [US10] Implement Redis health check (ping test)
|
||||
- [ ] T191 [US10] Implement PostgreSQL health check (simple query)
|
||||
- [ ] T192 [US10] Implement disk space check for recordings (warn if <10%)
|
||||
- [ ] T193 [US10] Create system router in src/api/routers/system.py: GET /health, GET /status
|
||||
- [ ] T194 [US10] Implement GET /health endpoint (public, returns basic status)
|
||||
- [ ] T195 [US10] Implement GET /status endpoint (authenticated, returns detailed metrics)
|
||||
- [ ] T196 [US10] Add Prometheus metrics endpoint at /metrics (request count, latency, errors, active streams, WebSocket connections)
|
||||
- [ ] T197 [US10] Implement background health monitoring task (check every 30s, alert on failures)
|
||||
|
||||
**Verify**: Run tests T184-T186 - they should now PASS
|
||||
|
||||
**Checkpoint**: Health monitoring functional - status endpoints, metrics, component checks
|
||||
|
||||
---
|
||||
|
||||
## Phase 13: User Story 12 - GeViSoft Configuration Management (Priority: P1) ✅ IMPLEMENTED (2025-12-16)
|
||||
|
||||
**Goal**: Manage GeViSoft configuration (G-Core servers, action mappings) via REST API
|
||||
|
||||
**Implementation Status**: CRUD operations working with critical bug fixes applied
|
||||
|
||||
### Implementation Summary (Completed)
|
||||
|
||||
**REST API Endpoints**:
|
||||
- ✅ `GET /api/v1/configuration/servers` - List all G-Core servers
|
||||
- ✅ `GET /api/v1/configuration/servers/{server_id}` - Get single server
|
||||
- ✅ `POST /api/v1/configuration/servers` - Create new server
|
||||
- ⚠️ `PUT /api/v1/configuration/servers/{server_id}` - Update server (known bug)
|
||||
- ✅ `DELETE /api/v1/configuration/servers/{server_id}` - Delete server
|
||||
- ✅ `GET /api/v1/configuration/action-mappings` - List all action mappings
|
||||
- ✅ `GET /api/v1/configuration/action-mappings/{mapping_id}` - Get single mapping
|
||||
- ✅ `POST /api/v1/configuration/action-mappings` - Create mapping
|
||||
- ✅ `PUT /api/v1/configuration/action-mappings/{mapping_id}` - Update mapping
|
||||
- ✅ `DELETE /api/v1/configuration/action-mappings/{mapping_id}` - Delete mapping
|
||||
|
||||
**gRPC SDK Bridge**:
|
||||
- ✅ ConfigurationService implementation
|
||||
- ✅ SetupClient integration for .set file operations
|
||||
- ✅ FolderTreeParser for binary configuration parsing
|
||||
- ✅ FolderTreeWriter for configuration updates
|
||||
- ✅ CreateServer, UpdateServer, DeleteServer methods
|
||||
- ✅ CreateActionMapping, UpdateActionMapping, DeleteActionMapping methods
|
||||
- ✅ ReadConfigurationTree for querying configuration
|
||||
|
||||
**Critical Fixes**:
|
||||
- ✅ **Cascade Deletion Bug**: Fixed deletion order issue (delete in reverse order)
|
||||
- ✅ **Bool Type Handling**: Proper bool type usage for GeViSet compatibility
|
||||
- ✅ **Auto-increment Server IDs**: Find highest numeric ID and increment
|
||||
|
||||
**Test Scripts**:
|
||||
- ✅ `comprehensive_crud_test.py` - Full CRUD verification
|
||||
- ✅ `safe_delete_test.py` - Cascade deletion fix verification
|
||||
- ✅ `server_manager.py` - Production server management
|
||||
- ✅ `cleanup_to_base.py` - Configuration reset utility
|
||||
- ✅ `verify_config_via_grpc.py` - Configuration verification
|
||||
|
||||
**Documentation**:
|
||||
- ✅ `SERVER_CRUD_IMPLEMENTATION.md` - Complete implementation guide
|
||||
- ✅ `CRITICAL_BUG_FIX_DELETE.md` - Bug analysis and fix documentation
|
||||
- ✅ Updated spec.md with User Story 12 and functional requirements
|
||||
|
||||
**Known Issues**:
|
||||
- ⚠️ Server UPDATE method has "Server ID is required" bug (workaround: delete and recreate)
|
||||
|
||||
**Checkpoint**: Configuration management complete - can manage G-Core servers and action mappings via API
|
||||
|
||||
---
|
||||
|
||||
## Phase 14: Polish & Cross-Cutting Concerns
|
||||
|
||||
**Purpose**: Improvements that affect multiple user stories
|
||||
|
||||
- [ ] T198 [P] Add comprehensive API documentation to all endpoints (docstrings, parameter descriptions)
|
||||
- [ ] T199 [P] Create architecture diagram in docs/architecture.md with component interaction flows
|
||||
- [ ] T200 [P] Create SDK integration guide in docs/sdk-integration.md with connection patterns
|
||||
- [ ] T201 [P] Create deployment guide in docs/deployment.md (Windows Server, Docker, environment setup)
|
||||
- [ ] T202 [P] Add OpenAPI specification auto-generation from code annotations
|
||||
- [ ] T203 [P] Implement request/response logging with correlation IDs for debugging
|
||||
- [ ] T204 [P] Add performance profiling endpoints (debug mode only)
|
||||
- [ ] T205 [P] Create load testing scripts for concurrent streams and WebSocket connections
|
||||
- [ ] T206 [P] Implement graceful shutdown handling (close connections, flush logs)
|
||||
- [ ] T207 [P] Add TLS/HTTPS configuration guide and certificate management
|
||||
- [ ] T208 [P] Security hardening: Remove stack traces from production errors, sanitize logs
|
||||
- [ ] T209 [P] Add database connection pooling optimization
|
||||
- [ ] T210 [P] Implement API response caching for camera lists (Redis cache, 60s TTL)
|
||||
- [ ] T211 [P] Create GitHub Actions CI/CD pipeline (run tests, build Docker images)
|
||||
- [ ] T212 [P] Add code coverage reporting (target 80% minimum)
|
||||
- [ ] T213 Validate quickstart.md by following guide end-to-end
|
||||
- [ ] T214 Create README.md with project overview, links to documentation
|
||||
- [ ] T215 Final security audit: Check for OWASP top 10 vulnerabilities
|
||||
|
||||
---
|
||||
|
||||
## Dependencies & Execution Order
|
||||
|
||||
### Phase Dependencies
|
||||
|
||||
- **Setup (Phase 1)**: No dependencies - can start immediately
|
||||
- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories
|
||||
- **User Stories (Phase 3-12)**: All depend on Foundational phase completion
|
||||
- User Story 1 (P1): Authentication - NO dependencies on other stories
|
||||
- User Story 2 (P1): Live Streaming - Requires User Story 1 (auth for protected endpoints)
|
||||
- User Story 3 (P1): PTZ Control - Requires User Story 1 (auth) and User Story 2 (camera service exists)
|
||||
- User Story 4 (P1): Event Notifications - Requires User Story 1 (auth), User Story 2 (camera service)
|
||||
- User Story 5 (P2): Recording Management - Requires User Story 1 (auth), User Story 2 (camera service)
|
||||
- User Story 6 (P2): Analytics Config - Requires User Story 1 (auth), User Story 2 (camera service), User Story 4 (events)
|
||||
- User Story 7 (P2): Multi-Camera - Extends User Story 2 (camera service)
|
||||
- User Story 8 (P3): NPR Integration - Requires User Story 4 (events), User Story 6 (analytics)
|
||||
- User Story 9 (P3): Video Export - Requires User Story 5 (recording management)
|
||||
- User Story 10 (P3): Health Monitoring - Can start after Foundational, but best after all services exist
|
||||
- **Polish (Phase 13)**: Depends on all desired user stories being complete
|
||||
|
||||
### Critical Path (Sequential)
|
||||
|
||||
```
|
||||
Phase 1: Setup
|
||||
↓
|
||||
Phase 2: Foundational (BLOCKS all user stories)
|
||||
↓
|
||||
Phase 3: User Story 1 - Authentication (BLOCKS all protected endpoints)
|
||||
↓
|
||||
Phase 4: User Story 2 - Live Streaming (BLOCKS camera-dependent features)
|
||||
↓
|
||||
Phase 5: User Story 3 - PTZ Control
|
||||
↓
|
||||
Phase 6: User Story 4 - Event Notifications (BLOCKS analytics)
|
||||
↓
|
||||
[Phase 7-12 can proceed in parallel after their dependencies are met]
|
||||
↓
|
||||
Phase 13: Polish
|
||||
```
|
||||
|
||||
### User Story Dependencies
|
||||
|
||||
- **US1 (Authentication)**: No dependencies - can start after Foundational
|
||||
- **US2 (Live Streaming)**: Depends on US1 completion
|
||||
- **US3 (PTZ Control)**: Depends on US1, US2 completion
|
||||
- **US4 (Event Notifications)**: Depends on US1, US2 completion
|
||||
- **US5 (Recording Management)**: Depends on US1, US2 completion
|
||||
- **US6 (Analytics Config)**: Depends on US1, US2, US4 completion
|
||||
- **US7 (Multi-Camera)**: Depends on US2 completion
|
||||
- **US8 (NPR Integration)**: Depends on US4, US6 completion
|
||||
- **US9 (Video Export)**: Depends on US5 completion
|
||||
- **US10 (Health Monitoring)**: Can start after Foundational
|
||||
- **US12 (Configuration Management)**: ✅ COMPLETED - Depends on Foundational only
|
||||
|
||||
### Parallel Opportunities
|
||||
|
||||
**Within Phases**:
|
||||
- Phase 1 (Setup): T004-T010 can run in parallel (all marked [P])
|
||||
- Phase 2 (Foundational): T014-T015, T019-T021, T023-T024, T028-T029 can run in parallel
|
||||
|
||||
**Within User Stories**:
|
||||
- US1 Tests: T030-T034 can run in parallel
|
||||
- US1 Models: T035-T036 can run in parallel
|
||||
- US1 Schemas: T038 independent
|
||||
- US2 Tests: T049-T055 can run in parallel
|
||||
- US2 Models: T063-T064 can run in parallel
|
||||
- US2 Schemas: T066-T067 can run in parallel
|
||||
- [Similar pattern for all user stories]
|
||||
|
||||
**Across User Stories** (if team capacity allows):
|
||||
- After Foundational completes: US1, US10, US12 can start in parallel
|
||||
- After US1 completes: US2, US5 can start in parallel
|
||||
- After US2 completes: US3, US4, US7 can start in parallel
|
||||
- After US4 completes: US6 can start
|
||||
- After US5 completes: US9 can start
|
||||
- After US6 completes: US8 can start
|
||||
- US12 ✅ COMPLETED (Configuration Management)
|
||||
|
||||
**Polish Phase**: T198-T212, T214-T215 all marked [P] can run in parallel
|
||||
|
||||
---
|
||||
|
||||
## Parallel Example: User Story 2 (Live Streaming)
|
||||
|
||||
```bash
|
||||
# Step 1: Write all tests in parallel (TDD - ensure they FAIL)
|
||||
Task T049: Contract test for GET /cameras
|
||||
Task T050: Contract test for GET /cameras/{id}
|
||||
Task T051: Contract test for POST /cameras/{id}/stream
|
||||
Task T052: Contract test for DELETE /cameras/{id}/stream/{stream_id}
|
||||
Task T053: Integration test for stream lifecycle
|
||||
Task T054: Unit test for CameraService (Python)
|
||||
Task T055: Unit test for CameraService (C#)
|
||||
|
||||
# Step 2: Create models in parallel
|
||||
Task T063: Camera model
|
||||
Task T064: Stream model
|
||||
|
||||
# Step 3: Create schemas in parallel
|
||||
Task T066: Camera schemas
|
||||
Task T067: Stream schemas
|
||||
|
||||
# Step 4: Implement services sequentially (dependency on models)
|
||||
Task T068: CameraService (depends on T063, T064)
|
||||
Task T069: StreamService (depends on T068)
|
||||
|
||||
# Step 5: Implement SDK Bridge sequentially
|
||||
Task T056: CameraService.cs (depends on gRPC proto T047)
|
||||
Task T059: StreamService.cs (depends on gRPC proto T048)
|
||||
|
||||
# Step 6: Implement routers sequentially (depends on services)
|
||||
Task T071: Cameras router
|
||||
Task T072: Stream endpoints
|
||||
|
||||
# Verify: Run tests T049-T055 - they should now PASS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
### MVP First (User Stories 1-4 Only)
|
||||
|
||||
**Rationale**: US1-US4 are all P1 and deliver core surveillance functionality
|
||||
|
||||
1. ✅ Complete Phase 1: Setup
|
||||
2. ✅ Complete Phase 2: Foundational (CRITICAL - blocks all stories)
|
||||
3. ✅ Complete Phase 3: User Story 1 (Authentication) - STOP and TEST
|
||||
4. ✅ Complete Phase 4: User Story 2 (Live Streaming) - STOP and TEST
|
||||
5. ✅ Complete Phase 5: User Story 3 (PTZ Control) - STOP and TEST
|
||||
6. ✅ Complete Phase 6: User Story 4 (Event Notifications) - STOP and TEST
|
||||
7. **STOP and VALIDATE**: Test all P1 stories together as integrated MVP
|
||||
8. Deploy/demo MVP
|
||||
|
||||
**MVP Delivers**:
|
||||
- ✅ Secure authentication with RBAC
|
||||
- ✅ Live video streaming from cameras
|
||||
- ✅ PTZ camera control
|
||||
- ✅ Real-time event notifications
|
||||
|
||||
**Not in MVP** (can add incrementally):
|
||||
- Recording management (US5)
|
||||
- Analytics configuration (US6)
|
||||
- Multi-camera enhancements (US7)
|
||||
- NPR integration (US8)
|
||||
- Video export (US9)
|
||||
- Health monitoring (US10)
|
||||
|
||||
### Incremental Delivery (After MVP)
|
||||
|
||||
1. **MVP** (US1-4) → Deploy → Validate
|
||||
2. **+Recording** (US5) → Deploy → Validate
|
||||
3. **+Analytics** (US6) → Deploy → Validate
|
||||
4. **+Multi-Camera** (US7) → Deploy → Validate
|
||||
5. **+NPR** (US8) → Deploy → Validate
|
||||
6. **+Export** (US9) → Deploy → Validate
|
||||
7. **+Health** (US10) → Deploy → Validate
|
||||
8. **+Polish** (Phase 13) → Final Release
|
||||
|
||||
Each increment adds value without breaking previous functionality.
|
||||
|
||||
### Parallel Team Strategy
|
||||
|
||||
With 3 developers after Foundational phase completes:
|
||||
|
||||
**Week 1-2**: All work on US1 together (foundational for everything)
|
||||
|
||||
**Week 3-4**:
|
||||
- Developer A: US2 (Live Streaming)
|
||||
- Developer B: Start US4 (Events - can partially proceed)
|
||||
- Developer C: Setup/tooling improvements
|
||||
|
||||
**Week 5-6**:
|
||||
- Developer A: US3 (PTZ - depends on US2)
|
||||
- Developer B: Complete US4 (Events)
|
||||
- Developer C: US5 (Recording)
|
||||
|
||||
**Week 7+**:
|
||||
- Developer A: US6 (Analytics)
|
||||
- Developer B: US7 (Multi-Camera)
|
||||
- Developer C: US9 (Export)
|
||||
|
||||
---
|
||||
|
||||
## Task Summary
|
||||
|
||||
**Total Tasks**: 215
|
||||
|
||||
**By Phase**:
|
||||
- Phase 1 (Setup): 10 tasks
|
||||
- Phase 2 (Foundational): 19 tasks
|
||||
- Phase 3 (US1 - Authentication): 17 tasks
|
||||
- Phase 4 (US2 - Live Streaming): 29 tasks
|
||||
- Phase 5 (US3 - PTZ Control): 15 tasks
|
||||
- Phase 6 (US4 - Event Notifications): 22 tasks
|
||||
- Phase 7 (US5 - Recording Management): 19 tasks
|
||||
- Phase 8 (US6 - Analytics Config): 18 tasks
|
||||
- Phase 9 (US7 - Multi-Camera): 9 tasks
|
||||
- Phase 10 (US8 - NPR Integration): 12 tasks
|
||||
- Phase 11 (US9 - Video Export): 14 tasks
|
||||
- Phase 12 (US10 - Health Monitoring): 14 tasks
|
||||
- Phase 13 (US12 - Configuration Management): ✅ COMPLETED (2025-12-16)
|
||||
- Phase 14 (Polish): 18 tasks
|
||||
|
||||
**MVP Tasks** (Phases 1-6): 112 tasks
|
||||
**Configuration Management**: ✅ Implemented separately (not part of original task breakdown)
|
||||
|
||||
**Tests**: 80+ test tasks (all marked TDD - write first, ensure FAIL)
|
||||
|
||||
**Parallel Tasks**: 100+ tasks marked [P]
|
||||
|
||||
**Estimated Timeline**:
|
||||
- MVP (US1-4): 8-10 weeks (1 developer) or 4-6 weeks (3 developers)
|
||||
- Full Feature Set (US1-10 + Polish): 16-20 weeks (1 developer) or 8-12 weeks (3 developers)
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- **[P] tasks**: Different files, no dependencies - safe to parallelize
|
||||
- **[Story] labels**: Maps task to specific user story for traceability
|
||||
- **TDD enforced**: All test tasks MUST be written first and FAIL before implementation
|
||||
- **Independent stories**: Each user story should be independently completable and testable
|
||||
- **Commit frequently**: After each task or logical group
|
||||
- **Stop at checkpoints**: Validate each story independently before proceeding
|
||||
- **MVP focus**: Complete US1-4 first for deployable surveillance system
|
||||
- **Avoid**: Vague tasks, same-file conflicts, cross-story dependencies that break independence
|
||||
|
||||
---
|
||||
|
||||
**Generated**: 2025-12-08
|
||||
**Updated**: 2025-12-16 (Configuration Management implemented)
|
||||
**Based on**: spec.md (12 user stories), plan.md (tech stack), data-model.md (8 entities), contracts/openapi.yaml (27+ endpoints)
|
||||
@@ -0,0 +1,291 @@
|
||||
# Database vs .SET File Structure Comparison
|
||||
|
||||
**Date:** 2025-12-12
|
||||
**Purpose:** Document differences between GeViSoft Database and .SET configuration file
|
||||
|
||||
## Executive Summary
|
||||
|
||||
GeViSoft uses **TWO distinct storage systems**:
|
||||
|
||||
1. **GeViDB.mdb** (Access Database) - Stores runtime event logs
|
||||
2. **.set File** (Binary Format) - Stores configuration and action mapping rules
|
||||
|
||||
They serve different purposes and have different structures.
|
||||
|
||||
---
|
||||
|
||||
## GeViSoft Database (GeViDB.mdb)
|
||||
|
||||
### Access Method
|
||||
|
||||
**Option 1: .NET SDK Wrapper** (Recommended)
|
||||
```csharp
|
||||
var db = new GeViDatabase();
|
||||
db.Create("localhost", "sysadmin", "plainTextPassword"); // No encoding needed!
|
||||
db.RegisterCallback();
|
||||
var result = db.Connect();
|
||||
|
||||
// Query actions
|
||||
db.SendQuery(new GeViDBQ_CreateActionQuery(0), out GeViMessage answer);
|
||||
```
|
||||
|
||||
**Password Encoding:**
|
||||
✅ **NOT REQUIRED** - The .NET wrapper (`GeViProcAPINET_4_0.dll`) handles password encoding internally.
|
||||
The `Create()` method signature explicitly says `plainTextPassword`.
|
||||
|
||||
**Option 2: Direct OleDB Access**
|
||||
```csharp
|
||||
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\GEVISOFT\DATABASE\GeViDB.mdb;Mode=Read;";
|
||||
// Direct SQL queries to Alarms, Actions tables
|
||||
```
|
||||
|
||||
### Database Structure
|
||||
|
||||
**Tables:**
|
||||
- `Alarms` - Alarm definitions
|
||||
- `Actions` - Runtime action event log
|
||||
- (Other configuration tables)
|
||||
|
||||
**Actions Table Content:**
|
||||
| PK | Action Data | Purpose |
|
||||
|----|-------------|---------|
|
||||
| 1 | `DataBaseReady()` | System initialization event |
|
||||
| 4 | `SystemError(0,1000,203,"GEVISERVER: dongle not found")` | System error log |
|
||||
| 5 | `SystemWarning(0,1000,206,"DEMO MODE GRANTED...")` | System warning |
|
||||
| 15 | `UserLogin(1,"sysadmin","","127.0.0.1")` | User authentication log |
|
||||
|
||||
**Key Characteristics:**
|
||||
- Stores **runtime events** and **logs**
|
||||
- **NOT** action mapping configuration
|
||||
- Grows over time as events occur
|
||||
- Query-able with SQL or SDK queries
|
||||
|
||||
---
|
||||
|
||||
## .SET File (Binary Configuration)
|
||||
|
||||
### Access Method
|
||||
|
||||
**SetupClient API:**
|
||||
```csharp
|
||||
// PASSWORD ENCODING REQUIRED for native API!
|
||||
var encodedPassword = new StringBuilder(256);
|
||||
GeViAPI_EncodeString(encodedPassword, password, 256);
|
||||
|
||||
GeViAPI_SetupClient_Create(out handle, alias, address, username,
|
||||
encodedPassword.ToString(), "", "");
|
||||
GeViAPI_SetupClient_Connect(handle, out result, 10000);
|
||||
GeViAPI_SetupClient_ReadSetup(handle, out buffer, out size, 60000);
|
||||
```
|
||||
|
||||
**Password Encoding:**
|
||||
❌ **REQUIRED** for `SetupClient` native API!
|
||||
Must call `GeViAPI_EncodeString()` before passing password.
|
||||
|
||||
### Binary Format Structure
|
||||
|
||||
```
|
||||
.set File (281,714 bytes)
|
||||
├── Header: "GeViSoft Parameters" (length-prefixed)
|
||||
├── Sections (multiple)
|
||||
│ ├── Alarms
|
||||
│ ├── Cameras
|
||||
│ ├── GeViIO
|
||||
│ ├── Clients
|
||||
│ └── Action Mapping Rules
|
||||
│ ├── "Rules" marker (05 52 75 6C 65 73)
|
||||
│ ├── Trigger Conditions
|
||||
│ └── Action Strings
|
||||
│ ├── Format: 07 01 40 <len_2bytes_LE> <data>
|
||||
│ └── Examples:
|
||||
│ • "GSC ViewerConnectLive V <- C"
|
||||
│ • "GNG PanLeft_101027"
|
||||
│ • "GSC warning: demo mode for 100 min"
|
||||
```
|
||||
|
||||
**Action Mappings Extracted:** 64 rules with 107 action strings
|
||||
|
||||
**Examples:**
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"fileOffset": 253894,
|
||||
"actions": [
|
||||
"GSC ViewerConnectLive V <- C",
|
||||
"GNG ViewerConnectLive V <- C_101027"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Key Characteristics:**
|
||||
- Stores **configuration** and **rules**
|
||||
- Defines trigger → action mappings
|
||||
- Static configuration (doesn't grow)
|
||||
- Can be exported/imported with GeViSet application
|
||||
- Binary format requires parsing
|
||||
|
||||
---
|
||||
|
||||
## Comparison Table
|
||||
|
||||
| Aspect | Database (GeViDB.mdb) | .SET File |
|
||||
|--------|----------------------|-----------|
|
||||
| **Purpose** | Runtime event logging | Configuration storage |
|
||||
| **Content** | System events, user logins, errors | Action mapping rules, system config |
|
||||
| **Password Encoding** | ❌ NOT needed (.NET wrapper) | ✅ REQUIRED (native SetupClient API) |
|
||||
| **Access Method** | GeViDatabase + SendQuery | SetupClient_ReadSetup |
|
||||
| **Data Type** | Event logs (dynamic) | Configuration rules (static) |
|
||||
| **Size** | Grows over time | Fixed per configuration |
|
||||
| **Format** | MS Access Database | Proprietary binary |
|
||||
| **Queryable** | SQL / SDK queries | Binary parsing only |
|
||||
| **Example Content** | `UserLogin(1,"sysadmin"...)` | `"GSC ViewerConnectLive V <- C"` |
|
||||
|
||||
---
|
||||
|
||||
## Password Encoding Summary
|
||||
|
||||
### When Encoding IS Required
|
||||
|
||||
**SetupClient Native API:**
|
||||
```cpp
|
||||
// C/C++ or P/Invoke
|
||||
GeViAPI_EncodeString(encodedPassword, plainPassword, 256);
|
||||
GeViAPI_SetupClient_Create(..., encodedPassword, ...);
|
||||
```
|
||||
|
||||
**Why:** The native `GeViProcAPI.dll` requires pre-encoded passwords.
|
||||
|
||||
### When Encoding is NOT Required
|
||||
|
||||
**.NET SDK Wrapper:**
|
||||
```csharp
|
||||
// C# using .NET wrapper
|
||||
var db = new GeViDatabase();
|
||||
db.Create(server, username, plainTextPassword); // Handles encoding internally
|
||||
```
|
||||
|
||||
**Why:** The .NET wrapper (`GeViProcAPINET_4_0.dll`) calls `GeViAPI_EncodeString` internally.
|
||||
|
||||
---
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Use Database When:
|
||||
- Querying recent system events
|
||||
- Checking user login history
|
||||
- Monitoring system errors/warnings
|
||||
- Real-time event tracking
|
||||
|
||||
### Use .SET File When:
|
||||
- Exporting/importing configuration
|
||||
- Backing up action mapping rules
|
||||
- Bulk editing action mappings
|
||||
- Understanding configured rules (not events)
|
||||
|
||||
---
|
||||
|
||||
## Tools Developed
|
||||
|
||||
### 1. QueryGeViDatabase
|
||||
**Purpose:** Query database for runtime events
|
||||
**Method:** .NET SDK wrapper
|
||||
**Password:** Plain text (wrapper handles encoding)
|
||||
|
||||
```bash
|
||||
QueryGeViDatabase.exe localhost sysadmin masterkey
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- System events
|
||||
- User logins
|
||||
- Errors/warnings
|
||||
- 100+ action event logs
|
||||
|
||||
### 2. DiagnoseSetupClient + GeViSetEditor
|
||||
**Purpose:** Read/parse .set configuration file
|
||||
**Method:** Native SetupClient API
|
||||
**Password:** Manually encoded with `GeViAPI_EncodeString`
|
||||
|
||||
```bash
|
||||
GeViSetEditor.exe to-json setup_config.dat output.json
|
||||
```
|
||||
|
||||
**Output:**
|
||||
- 64 action mapping rules
|
||||
- 107 action strings
|
||||
- Complete configuration in JSON
|
||||
|
||||
---
|
||||
|
||||
## Findings
|
||||
|
||||
1. **Database does NOT contain action mapping configuration**
|
||||
- Only stores runtime event logs
|
||||
- Cannot use database queries to read action mapping rules
|
||||
|
||||
2. **.SET file is the ONLY source for action mapping configuration**
|
||||
- Must use SetupClient API
|
||||
- Must parse binary format
|
||||
- Contains all 64 action mapping rules
|
||||
|
||||
3. **Password encoding depends on API layer:**
|
||||
- .NET wrapper: No encoding needed
|
||||
- Native API: Encoding required
|
||||
- Both work, different use cases
|
||||
|
||||
4. **Two distinct data flows:**
|
||||
```
|
||||
Configuration Flow:
|
||||
GeViSet App → .SET File → SetupClient API → Binary Parser → JSON
|
||||
|
||||
Events Flow:
|
||||
GeViServer → Database → SendQuery → Event Logs
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Recommendations
|
||||
|
||||
1. **For Action Mapping Management:**
|
||||
- Use SetupClient API to read .set files
|
||||
- Parse binary format to extract mappings
|
||||
- Export to JSON/Excel for editing
|
||||
- Rebuild .set file and write back
|
||||
|
||||
2. **For Event Monitoring:**
|
||||
- Use GeViDatabase queries
|
||||
- No binary parsing needed
|
||||
- Direct SQL or SDK queries
|
||||
|
||||
3. **Password Handling:**
|
||||
- Use .NET wrapper when possible (simpler)
|
||||
- Only use native API when .NET wrapper doesn't support the operation
|
||||
- Always encode passwords for native SetupClient API
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. ✅ **Completed:**
|
||||
- Database connection (both methods)
|
||||
- SetupClient connection with password encoding
|
||||
- Binary parser for .set files
|
||||
- JSON export of action mappings
|
||||
|
||||
2. **In Progress:**
|
||||
- Excel export for user-friendly editing
|
||||
- Enhanced parser for trigger conditions
|
||||
|
||||
3. **Future:**
|
||||
- Add/modify/delete action mappings
|
||||
- Binary writer for modifications
|
||||
- Web UI for configuration management
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- SetupClient API: `C:\GEVISOFT\Examples\VS2010CPP\GeViSoftSDK\Include\GeViProcAPI.h`
|
||||
- .NET Wrapper: `C:\GEVISOFT\GeViProcAPINET_4_0.dll`
|
||||
- Database: `C:\GEVISOFT\DATABASE\GeViDB.mdb`
|
||||
- Research Notes: `geutebruck-api/specs/002-geviset-file-format/research.md`
|
||||
274
geutebruck-api/specs/002-geviset-file-format/research.md
Normal file
274
geutebruck-api/specs/002-geviset-file-format/research.md
Normal file
@@ -0,0 +1,274 @@
|
||||
# GeViSet File Format Research Notes
|
||||
|
||||
## Binary Format Discoveries
|
||||
|
||||
### Header Analysis
|
||||
|
||||
**File**: setup_config_20251212_122429.dat (281,714 bytes)
|
||||
|
||||
```
|
||||
Offset Hex ASCII
|
||||
0000: 00 13 47 65 56 69 53 6F 66 74 20 50 61 72 61 6D ..GeViSoft Param
|
||||
0010: 65 74 65 72 73 eters
|
||||
```
|
||||
|
||||
**Structure**:
|
||||
- `00`: Optional null byte (not always present)
|
||||
- `13`: Length byte (0x13 = 19 bytes)
|
||||
- `47 65 56 69 53 6F 66 74 20 50 61 72 61 6D 65 74 65 72 73`: "GeViSoft Parameters"
|
||||
|
||||
**Note**: This is NOT a standard Pascal string (no 0x07 marker), just length + data.
|
||||
|
||||
### Section Structure
|
||||
|
||||
Sections appear to follow this pattern:
|
||||
|
||||
```
|
||||
07 <len> <section_name> // Pascal string for section name
|
||||
... items ...
|
||||
05 52 75 6C 65 73 // "Rules" marker (if rules present)
|
||||
... rules ...
|
||||
```
|
||||
|
||||
### Rules Marker Pattern
|
||||
|
||||
Found 65 occurrences of pattern: `05 52 75 6C 65 73` ("Rules")
|
||||
|
||||
Key offsets:
|
||||
- 252,278 (0x3D976)
|
||||
- 252,717 (0x3DB2D)
|
||||
- 253,152 (0x3DCE0)
|
||||
- ... (65 total)
|
||||
|
||||
After "Rules" marker:
|
||||
```
|
||||
05 52 75 6C 65 73 // "Rules"
|
||||
02 00 00 00 // Count? (2 rules?)
|
||||
00 01 31 // Unknown metadata
|
||||
05 00 00 00 // Another count/offset?
|
||||
07 01 40 ... // Start of action string
|
||||
```
|
||||
|
||||
### Action String Pattern
|
||||
|
||||
**Format**: `07 01 40 <len_2bytes_LE> <action_data>`
|
||||
|
||||
**Examples from file**:
|
||||
|
||||
1. At offset 252,291:
|
||||
```
|
||||
07 01 40 1C 00 47 53 43 20 56 69 65 77 65 72 43 6F 6E 6E 65 63 74 4C 69 76 65 20 56 20 3C 2D 20 43
|
||||
│ │ │ │ │
|
||||
│ │ │ └──┴─ Length: 0x001C (28 bytes)
|
||||
│ │ └─ Action marker
|
||||
│ └─ Subtype
|
||||
└─ String type
|
||||
|
||||
Action: "GSC ViewerConnectLive V <- C"
|
||||
```
|
||||
|
||||
2. At offset 258,581:
|
||||
```
|
||||
07 01 40 11 00 47 53 43 20 56 69 65 77 65 72 43 6C 65 61 72 20 56
|
||||
Length: 0x0011 (17 bytes)
|
||||
Action: "GSC ViewerClear V"
|
||||
```
|
||||
|
||||
### Data Type Markers
|
||||
|
||||
| Marker | Type | Evidence |
|
||||
|--------|---------|-----------------------------------------------|
|
||||
| 0x01 | Boolean | Followed by 0x00 or 0x01 |
|
||||
| 0x04 | Int32 | Followed by 4 bytes (little-endian) |
|
||||
| 0x07 | String | Pascal string: <len> <data> |
|
||||
| 0x07 0x01 0x40 | Action | Special action string format |
|
||||
|
||||
### Section Names Found
|
||||
|
||||
From file analysis:
|
||||
- "Description" (most common - appears 832 times)
|
||||
- "IpHost"
|
||||
- "GscAction"
|
||||
- "GCoreAction"
|
||||
- "Alarms"
|
||||
- "Clients"
|
||||
- "GeViIO"
|
||||
|
||||
### Action Mappings Extracted
|
||||
|
||||
Successfully extracted 64 action mappings from the file:
|
||||
|
||||
**PTZ Camera Controls** (Camera 101027):
|
||||
1. PanLeft_101027
|
||||
2. PanRight_101027
|
||||
3. PanStop_101027
|
||||
4. TiltDown_101027
|
||||
5. TiltUp_101027
|
||||
6. TiltStop_101027
|
||||
7. ZoomIn_101027
|
||||
8. ZoomOut_101027
|
||||
9. ZoomStop_101027
|
||||
10. FocusFar 128_C101027
|
||||
11. FocusNear 128_C101027
|
||||
12. FocusStop_101027
|
||||
13. IrisOpen_101027
|
||||
14. IrisClose_101027
|
||||
15. IrisStop_101027
|
||||
|
||||
**Preset Positions**:
|
||||
16. MoveToDefaultPostion_101027
|
||||
17. ClearDefaultPostion_101027
|
||||
18. SaveDafaultPostion_101027
|
||||
19. MoveToPresentPostion
|
||||
20. ClearPresentPostion
|
||||
21. SavePresentPostion
|
||||
|
||||
**Viewer Controls**:
|
||||
22. ViewerConnectLive V <- C
|
||||
23. ViewerConnectLive V <- C_101027
|
||||
24. ViewerClear V
|
||||
25. VC live
|
||||
|
||||
**System Messages**:
|
||||
26-35. Demo mode warnings (100, 90, 80... 10 min)
|
||||
36. info: licence satisfied
|
||||
37. info: re_porter mode active
|
||||
38. error: "GeViIO Client: start of interface failed"
|
||||
39. error: "GeViIO Client: interface lost"
|
||||
40. warning: "GeViSoft Server: client warning"
|
||||
|
||||
### Platform Variations
|
||||
|
||||
Actions often have multiple platform-specific versions:
|
||||
|
||||
```
|
||||
GSC (GeViScope):
|
||||
"GSC ViewerConnectLive V <- C"
|
||||
|
||||
GNG (G-Net-Guard):
|
||||
"GNG ViewerConnectLive V <- C_101027"
|
||||
|
||||
GCore:
|
||||
"GCore <action>"
|
||||
```
|
||||
|
||||
### Unknown Patterns
|
||||
|
||||
Several byte patterns whose purpose is unclear:
|
||||
|
||||
1. **Pattern**: `04 02 40 40 64 00 00 00 00`
|
||||
- Appears before many action strings
|
||||
- Possibly metadata or flags
|
||||
|
||||
2. **Pattern**: `00 00 00 00 00 01 31 05 00 00 00`
|
||||
- Appears after "Rules" marker
|
||||
- Could be counts, offsets, or IDs
|
||||
|
||||
3. **Pattern**: `0C 4D 61 70 70 69 6E 67 52 75 6C 65 73`
|
||||
- `0C MappingRules` (length-prefixed, no 0x07)
|
||||
- At offset 252,172
|
||||
- Different string format than Pascal strings
|
||||
|
||||
## Testing Results
|
||||
|
||||
### Round-Trip Test
|
||||
|
||||
```
|
||||
✅ SUCCESS!
|
||||
Original: 281,714 bytes
|
||||
Parsed: 64 action mappings
|
||||
Written: 281,714 bytes
|
||||
Comparison: IDENTICAL (byte-for-byte)
|
||||
```
|
||||
|
||||
**Conclusion**: Safe to write back to server with current preservation approach.
|
||||
|
||||
### SetupClient API Test
|
||||
|
||||
```
|
||||
✅ Connection successful
|
||||
✅ Read setup: 281,714 bytes
|
||||
✅ Write setup: Not tested yet (waiting for full parser)
|
||||
✅ Password encryption: Working (GeViAPI_EncodeString)
|
||||
```
|
||||
|
||||
## Next Research Areas
|
||||
|
||||
### 1. Trigger Parsing
|
||||
|
||||
Need to understand trigger structure:
|
||||
```
|
||||
.VideoInput = True
|
||||
.InputContact = False
|
||||
```
|
||||
|
||||
These appear before action strings in rules.
|
||||
|
||||
### 2. Metadata Bytes
|
||||
|
||||
The bytes between sections and before/after rules:
|
||||
- What do they represent?
|
||||
- Are they counts? Offsets? Flags?
|
||||
- Can they be modified?
|
||||
|
||||
### 3. Section Relationships
|
||||
|
||||
How do sections reference each other?
|
||||
- Do cameras reference alarm rules?
|
||||
- Do action mappings reference I/O ports?
|
||||
- How are IDs assigned?
|
||||
|
||||
### 4. Format Versioning
|
||||
|
||||
Does the format change between GeViSoft versions?
|
||||
- Version 6.0.1.5 (current)
|
||||
- How to detect version?
|
||||
- Compatibility considerations?
|
||||
|
||||
## Tools Used for Analysis
|
||||
|
||||
### Python Scripts
|
||||
|
||||
```python
|
||||
# Find all "Rules" patterns
|
||||
import struct
|
||||
with open('setup_config.dat', 'rb') as f:
|
||||
data = f.read()
|
||||
|
||||
needle = b'Rules'
|
||||
pos = 0
|
||||
while True:
|
||||
pos = data.find(needle, pos)
|
||||
if pos == -1: break
|
||||
print(f'Found at offset {pos} (0x{pos:X})')
|
||||
pos += 1
|
||||
```
|
||||
|
||||
### Hex Editors
|
||||
|
||||
- HxD
|
||||
- 010 Editor
|
||||
- VS Code with hex extension
|
||||
|
||||
### Binary Analysis
|
||||
|
||||
- Custom C# parser
|
||||
- Grep for pattern matching
|
||||
- Byte comparison tools
|
||||
|
||||
## References
|
||||
|
||||
- TestMKS.set (279,860 bytes) - Original test file
|
||||
- setup_config_20251212_122429.dat (281,714 bytes) - Live server config
|
||||
- GeViSoft SDK Documentation
|
||||
- GeViProcAPI.h header file
|
||||
|
||||
## Change Log
|
||||
|
||||
| Date | Discovery |
|
||||
|------------|----------------------------------------------|
|
||||
| 2024-12-12 | Initial binary analysis |
|
||||
| 2024-12-12 | Discovered action string format |
|
||||
| 2024-12-12 | Found 65 "Rules" markers |
|
||||
| 2024-12-12 | Extracted 64 action mappings successfully |
|
||||
| 2024-12-12 | Verified byte-for-byte round-trip |
|
||||
617
geutebruck-api/specs/002-geviset-file-format/spec.md
Normal file
617
geutebruck-api/specs/002-geviset-file-format/spec.md
Normal file
@@ -0,0 +1,617 @@
|
||||
# GeViSet File Format Reverse Engineering Specification
|
||||
|
||||
**Version:** 1.0
|
||||
**Date:** 2024-12-12
|
||||
**Status:** In Progress
|
||||
|
||||
## Overview
|
||||
|
||||
This specification documents the reverse engineering effort to fully parse, understand, and manipulate the GeViSoft `.set` configuration file format. The goal is to enable programmatic reading, editing, and writing of GeViServer configurations, particularly action mappings.
|
||||
|
||||
## Background
|
||||
|
||||
### What is a .set File?
|
||||
|
||||
- **Source**: Exported from GeViSet application or read via `GeViAPI_SetupClient_ReadSetup`
|
||||
- **Purpose**: Complete GeViServer configuration (cameras, alarms, action mappings, users, etc.)
|
||||
- **Format**: Proprietary binary format with "GeViSoft Parameters" header
|
||||
- **Size**: Typically 200-300 KB for production configurations
|
||||
- **Use Case**: Backup, migration, and programmatic configuration management
|
||||
|
||||
### Current State
|
||||
|
||||
**What Works:**
|
||||
- ✅ Read .set file from GeViServer via SetupClient API
|
||||
- ✅ Extract 64 action mappings from binary data
|
||||
- ✅ Write back byte-for-byte identical (round-trip verified)
|
||||
- ✅ Password encryption with `GeViAPI_EncodeString`
|
||||
|
||||
**What's Missing:**
|
||||
- ❌ Full structure parsing (all sections, all items)
|
||||
- ❌ Understanding of all data types and relationships
|
||||
- ❌ Ability to add NEW action mappings
|
||||
- ❌ JSON representation of complete structure
|
||||
- ❌ Comprehensive Excel export/import
|
||||
|
||||
## Requirements
|
||||
|
||||
### Primary Request
|
||||
|
||||
> "I want to do full reverse engineering - I need to parse the whole file and maybe to json format in the first phase and then we will revert this json or its parts to excel"
|
||||
|
||||
### Key Requirements
|
||||
|
||||
1. **Parse Entire File Structure**
|
||||
- All sections (Alarms, Clients, GeViIO, Cameras, ActionMappings, etc.)
|
||||
- All configuration items (key-value pairs)
|
||||
- All rules and triggers
|
||||
- All metadata and relationships
|
||||
|
||||
2. **JSON Serialization**
|
||||
- Complete structure in JSON format
|
||||
- Human-readable and editable
|
||||
- Preserves all data and relationships
|
||||
- Round-trip safe (JSON → Binary → JSON)
|
||||
|
||||
3. **Excel Export/Import**
|
||||
- Export action mappings to Excel
|
||||
- User-friendly editing interface
|
||||
- Add new mappings
|
||||
- Delete existing mappings
|
||||
- Import back to JSON
|
||||
|
||||
4. **Safety & Validation**
|
||||
- Verify integrity before writing to server
|
||||
- Backup original configuration
|
||||
- Validate against schema
|
||||
- Error handling and recovery
|
||||
|
||||
## Architecture
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ GeViServer │
|
||||
│ ↓ │
|
||||
│ SetupClient API (ReadSetup) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
.set file (binary)
|
||||
281,714 bytes
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 1: Binary Parser │
|
||||
│ - Parse header │
|
||||
│ - Parse all sections │
|
||||
│ - Parse all items │
|
||||
│ - Parse all rules │
|
||||
│ - Extract action mappings │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
JSON Structure
|
||||
(full configuration representation)
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 2: JSON Processing │
|
||||
│ - Validate structure │
|
||||
│ - Transform for editing │
|
||||
│ - Extract sections │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 3: Excel Export │
|
||||
│ - Convert action mappings to Excel │
|
||||
│ - User edits in Excel │
|
||||
│ - Add/delete/modify mappings │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
Excel file
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 4: Excel Import │
|
||||
│ - Read Excel changes │
|
||||
│ - Validate data │
|
||||
│ - Update JSON structure │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
JSON Structure
|
||||
(modified)
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PHASE 5: Binary Writer │
|
||||
│ - Rebuild .set file from JSON │
|
||||
│ - Maintain binary format │
|
||||
│ - Validate integrity │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
.set file (binary)
|
||||
↓
|
||||
SetupClient API (WriteSetup)
|
||||
↓
|
||||
GeViServer
|
||||
```
|
||||
|
||||
## Binary Format Analysis
|
||||
|
||||
### File Structure
|
||||
|
||||
```
|
||||
.set file
|
||||
├── Header
|
||||
│ ├── 0x00 (optional null byte)
|
||||
│ └── Pascal String: "GeViSoft Parameters" (0x07 <len> <data>)
|
||||
│
|
||||
├── Sections (multiple)
|
||||
│ ├── Section Name (Pascal String)
|
||||
│ ├── Items (key-value pairs)
|
||||
│ │ ├── Key (Pascal String)
|
||||
│ │ └── Value (typed)
|
||||
│ │ ├── 0x01 = Boolean
|
||||
│ │ ├── 0x04 = Integer (4 bytes)
|
||||
│ │ └── 0x07 = String (Pascal)
|
||||
│ │
|
||||
│ └── Rules Subsection
|
||||
│ ├── "Rules" marker (0x05 0x52 0x75 0x6C 0x65 0x73)
|
||||
│ ├── Count/Metadata
|
||||
│ └── Action Rules (multiple)
|
||||
│ ├── Trigger Properties
|
||||
│ │ └── .PropertyName = Boolean
|
||||
│ ├── Main Action String
|
||||
│ │ └── 0x07 0x01 0x40 <len_2bytes> <action_data>
|
||||
│ └── Action Variations
|
||||
│ ├── GscAction (GeViScope)
|
||||
│ ├── GNGAction (G-Net-Guard)
|
||||
│ └── GCoreAction (GCore)
|
||||
│
|
||||
└── Footer (metadata/checksums?)
|
||||
```
|
||||
|
||||
### Data Types Discovered
|
||||
|
||||
| Marker | Type | Format | Example |
|
||||
|--------|---------|----------------------------------|----------------------------|
|
||||
| 0x01 | Boolean | 0x01 <value> | 0x01 0x01 = true |
|
||||
| 0x04 | Integer | 0x04 <4-byte little-endian> | 0x04 0x0A 0x00 0x00 0x00 |
|
||||
| 0x07 | String | 0x07 <len> <data> | 0x07 0x0B "Description" |
|
||||
| 0x07 0x01 0x40 | Action | 0x07 0x01 0x40 <len_2bytes> <data> | Action string format |
|
||||
|
||||
### Action String Format
|
||||
|
||||
Pattern: `07 01 40 <len_2bytes_LE> <action_text>`
|
||||
|
||||
Example:
|
||||
```
|
||||
07 01 40 1C 00 47 53 43 20 56 69 65 77 65 72 43 6F 6E 6E 65 63 74 4C 69 76 65...
|
||||
│ │ │ │ │ └─ "GSC ViewerConnectLive V <- C"
|
||||
│ │ │ └──┴─ Length: 0x001C (28 bytes)
|
||||
│ │ └─ 0x40 (action marker)
|
||||
│ └─ 0x01 (subtype)
|
||||
└─ 0x07 (string type)
|
||||
```
|
||||
|
||||
### Sections Found
|
||||
|
||||
From file analysis, sections include:
|
||||
- **Alarms**: Alarm configurations
|
||||
- **Clients**: Client connections
|
||||
- **GeViIO**: Digital I/O configurations
|
||||
- **Cameras**: Camera settings
|
||||
- **Description**: Various descriptive entries
|
||||
- **IpHost**: Network configurations
|
||||
- **ActionMappings**: Trigger → Action rules (our focus)
|
||||
|
||||
## JSON Schema
|
||||
|
||||
### Complete Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string",
|
||||
"description": "Parser version"
|
||||
},
|
||||
"header": {
|
||||
"type": "string",
|
||||
"description": "File header (GeViSoft Parameters)"
|
||||
},
|
||||
"sections": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/Section"
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"Section": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ConfigItem"
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionRule"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ConfigItem": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"key": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{ "type": "integer" },
|
||||
{ "type": "string" }
|
||||
]
|
||||
},
|
||||
"type": {
|
||||
"enum": ["boolean", "integer", "string"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ActionRule": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"triggers": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"mainAction": {
|
||||
"type": "string"
|
||||
},
|
||||
"variations": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/ActionVariation"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ActionVariation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"platform": {
|
||||
"enum": ["GSC", "GNG", "GCore"]
|
||||
},
|
||||
"actionString": {
|
||||
"type": "string"
|
||||
},
|
||||
"serverType": {
|
||||
"type": "string"
|
||||
},
|
||||
"serverName": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Example JSON Output
|
||||
|
||||
```json
|
||||
{
|
||||
"version": "1.0",
|
||||
"header": "GeViSoft Parameters",
|
||||
"sections": [
|
||||
{
|
||||
"name": "ActionMappings",
|
||||
"items": [],
|
||||
"rules": [
|
||||
{
|
||||
"id": 1,
|
||||
"triggers": {
|
||||
"InputContact": true,
|
||||
"VideoInput": false
|
||||
},
|
||||
"mainAction": "AlternateContact(2, 1000, 500)",
|
||||
"variations": [
|
||||
{
|
||||
"platform": "GSC",
|
||||
"actionString": "GSC ViewerConnectLive V <- C_101027",
|
||||
"serverType": "GeViScope",
|
||||
"serverName": "GEVISCOPE"
|
||||
},
|
||||
{
|
||||
"platform": "GNG",
|
||||
"actionString": "GNG PanLeft_101027",
|
||||
"serverType": "",
|
||||
"serverName": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Alarms",
|
||||
"items": [
|
||||
{
|
||||
"key": "AlarmCount",
|
||||
"value": 5,
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"key": "Enabled",
|
||||
"value": true,
|
||||
"type": "boolean"
|
||||
}
|
||||
],
|
||||
"rules": []
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Complete Binary Parser ✅
|
||||
|
||||
**Goal**: Parse entire .set file structure into memory
|
||||
|
||||
**Components**:
|
||||
- ✅ Header parser
|
||||
- 🚧 Section parser (all types)
|
||||
- 🚧 Item parser (all data types)
|
||||
- 🚧 Rules parser (complete structure)
|
||||
- 🚧 Action variation parser
|
||||
|
||||
**Status**: Basic parser exists, needs enhancement for full structure
|
||||
|
||||
### Phase 2: JSON Serialization 🚧
|
||||
|
||||
**Goal**: Convert parsed structure to JSON
|
||||
|
||||
**Components**:
|
||||
- JSON serializer
|
||||
- Schema validator
|
||||
- Round-trip tester (Binary → JSON → Binary)
|
||||
|
||||
**Deliverables**:
|
||||
- `SetFileToJson` converter
|
||||
- JSON schema definition
|
||||
- Validation tools
|
||||
|
||||
### Phase 3: Excel Export 🚧
|
||||
|
||||
**Goal**: Export action mappings to Excel for editing
|
||||
|
||||
**Components**:
|
||||
- Excel writer (EPPlus library)
|
||||
- Action mapping table generator
|
||||
- Template with formulas/validation
|
||||
|
||||
**Excel Structure**:
|
||||
```
|
||||
Sheet: ActionMappings
|
||||
| Rule ID | Trigger Type | Trigger Param | Action 1 | Action 2 | Action 3 |
|
||||
|---------|--------------|---------------|----------|----------|----------|
|
||||
| 1 | InputContact | 3, false | Alternate| Viewer | |
|
||||
| 2 | VideoInput | 4, true | CrossSwi | VCChange | |
|
||||
```
|
||||
|
||||
### Phase 4: Excel Import 🚧
|
||||
|
||||
**Goal**: Import edited Excel back to JSON
|
||||
|
||||
**Components**:
|
||||
- Excel reader
|
||||
- Validation engine
|
||||
- Diff generator (show changes)
|
||||
- JSON merger
|
||||
|
||||
### Phase 5: Binary Writer 🚧
|
||||
|
||||
**Goal**: Rebuild .set file from JSON
|
||||
|
||||
**Components**:
|
||||
- Binary writer
|
||||
- Structure rebuilder
|
||||
- Validation
|
||||
- Backup mechanism
|
||||
|
||||
**Critical**: Must maintain binary compatibility!
|
||||
|
||||
### Phase 6: Testing & Validation 🚧
|
||||
|
||||
**Goal**: Ensure safety and correctness
|
||||
|
||||
**Test Cases**:
|
||||
1. Round-trip (Binary → JSON → Binary) = identical
|
||||
2. Round-trip (Binary → JSON → Excel → JSON → Binary) = valid
|
||||
3. Add new mapping → write → server accepts
|
||||
4. Modify existing mapping → write → server accepts
|
||||
5. Delete mapping → write → server accepts
|
||||
|
||||
## Current Progress
|
||||
|
||||
### Completed ✅
|
||||
|
||||
- [x] SetupClient API integration
|
||||
- [x] Password encryption
|
||||
- [x] Basic binary parsing (64 action mappings extracted)
|
||||
- [x] Safe round-trip (byte-for-byte identical)
|
||||
- [x] File structure analysis
|
||||
- [x] Data type discovery
|
||||
|
||||
### In Progress 🚧
|
||||
|
||||
- [ ] Complete section parsing
|
||||
- [ ] Full rule structure parsing
|
||||
- [ ] JSON serialization
|
||||
- [ ] Excel export
|
||||
- [ ] Binary writer for modifications
|
||||
|
||||
### Pending 📋
|
||||
|
||||
- [ ] Excel import
|
||||
- [ ] Add new mapping functionality
|
||||
- [ ] API endpoints
|
||||
- [ ] Documentation
|
||||
- [ ] Production deployment
|
||||
|
||||
## Technical Challenges
|
||||
|
||||
### Challenge 1: Unknown Metadata Bytes
|
||||
|
||||
**Problem**: Many byte sequences whose purpose is unknown
|
||||
|
||||
**Solution**:
|
||||
- Document all patterns found
|
||||
- Test modifications to understand behavior
|
||||
- Preserve unknown bytes during round-trip
|
||||
|
||||
### Challenge 2: Complex Nested Structure
|
||||
|
||||
**Problem**: Sections contain items and rules, rules contain variations
|
||||
|
||||
**Solution**:
|
||||
- Recursive parsing
|
||||
- Clear data model hierarchy
|
||||
- Offset tracking for debugging
|
||||
|
||||
### Challenge 3: Binary Format Changes
|
||||
|
||||
**Problem**: Format may vary between GeViSoft versions
|
||||
|
||||
**Solution**:
|
||||
- Version detection
|
||||
- Support multiple format versions
|
||||
- Graceful degradation
|
||||
|
||||
### Challenge 4: Action String Syntax
|
||||
|
||||
**Problem**: Action strings have complex syntax (parameters, types, etc.)
|
||||
|
||||
**Solution**:
|
||||
- Pattern matching
|
||||
- Action string parser
|
||||
- Validation against known action types
|
||||
|
||||
## Safety Considerations
|
||||
|
||||
### Before Writing to Server
|
||||
|
||||
1. ✅ **Verify round-trip**: Parse → Write → Compare = Identical
|
||||
2. ✅ **Backup original**: Always keep copy of working config
|
||||
3. ⚠️ **Test in dev**: Never test on production first
|
||||
4. ⚠️ **Validate structure**: Check against schema
|
||||
5. ⚠️ **Incremental changes**: Small changes, test frequently
|
||||
|
||||
### Error Handling
|
||||
|
||||
- Validate before write
|
||||
- Provide detailed error messages
|
||||
- Support rollback
|
||||
- Log all operations
|
||||
|
||||
## Tools & Libraries
|
||||
|
||||
### Development
|
||||
|
||||
- **Language**: C# / .NET 8.0
|
||||
- **Binary Parsing**: Custom binary reader
|
||||
- **JSON**: System.Text.Json
|
||||
- **Excel**: EPPlus (for .xlsx)
|
||||
- **Testing**: xUnit
|
||||
- **Logging**: Serilog
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
GeViSetEditor/
|
||||
├── GeViSetEditor.Core/
|
||||
│ ├── Models/
|
||||
│ │ ├── SetFileStructure.cs
|
||||
│ │ ├── Section.cs
|
||||
│ │ ├── ConfigItem.cs
|
||||
│ │ ├── ActionRule.cs
|
||||
│ │ └── ActionVariation.cs
|
||||
│ ├── Parsers/
|
||||
│ │ ├── SetFileBinaryParser.cs
|
||||
│ │ ├── SectionParser.cs
|
||||
│ │ └── RuleParser.cs
|
||||
│ ├── Writers/
|
||||
│ │ ├── SetFileBinaryWriter.cs
|
||||
│ │ └── JsonWriter.cs
|
||||
│ ├── Converters/
|
||||
│ │ ├── JsonToExcel.cs
|
||||
│ │ └── ExcelToJson.cs
|
||||
│ └── Validators/
|
||||
│ └── StructureValidator.cs
|
||||
├── GeViSetEditor.CLI/
|
||||
│ └── Commands/
|
||||
│ ├── ParseCommand.cs
|
||||
│ ├── ToJsonCommand.cs
|
||||
│ ├── ToExcelCommand.cs
|
||||
│ └── FromExcelCommand.cs
|
||||
└── GeViSetEditor.Tests/
|
||||
├── ParserTests.cs
|
||||
├── RoundTripTests.cs
|
||||
└── ValidationTests.cs
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
### Immediate (This Session)
|
||||
|
||||
1. ✅ Create specification document
|
||||
2. ✅ Update git repository
|
||||
3. 🚧 Implement complete binary parser
|
||||
4. 🚧 Implement JSON serialization
|
||||
5. 🚧 Test round-trip with JSON
|
||||
|
||||
### Short Term (Next Session)
|
||||
|
||||
1. Excel export implementation
|
||||
2. Excel import implementation
|
||||
3. Add new mapping functionality
|
||||
4. Comprehensive testing
|
||||
|
||||
### Long Term
|
||||
|
||||
1. Web UI for configuration management
|
||||
2. API endpoints
|
||||
3. Multi-version support
|
||||
4. Documentation and examples
|
||||
|
||||
## References
|
||||
|
||||
- GeViSoft SDK Documentation
|
||||
- SetupClient API Reference
|
||||
- Existing .set file samples (TestMKS.set, setup_config_*.dat)
|
||||
- Binary analysis notes
|
||||
- Round-trip test results
|
||||
|
||||
## Version History
|
||||
|
||||
| Version | Date | Changes |
|
||||
|---------|------------|--------------------------------------|
|
||||
| 1.0 | 2024-12-12 | Initial specification |
|
||||
|
||||
---
|
||||
|
||||
**Status**: Ready for full implementation
|
||||
**Priority**: High
|
||||
**Complexity**: High
|
||||
**Timeline**: 2-3 days estimated
|
||||
Reference in New Issue
Block a user