Initial commit: COPILOT D6 Flutter keyboard controller
Flutter web app replacing legacy WPF CCTV surveillance keyboard controller. Includes wall overview, section view with monitor grid, camera input, PTZ control, alarm/lock/sequence BLoCs, and legacy-matching UI styling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
120
Docs/legacy-architecture/migration-comparison.md
Normal file
120
Docs/legacy-architecture/migration-comparison.md
Normal file
@@ -0,0 +1,120 @@
|
||||
---
|
||||
title: "Legacy → Flutter Migration Comparison"
|
||||
description: "Side-by-side comparison of legacy WPF architecture vs new Flutter system"
|
||||
---
|
||||
|
||||
# Legacy → Flutter Migration Comparison
|
||||
|
||||
## Architecture Comparison
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "Legacy (WPF)"
|
||||
L_HW["Hardware Keyboard<br/>Serial + HID"] --> L_App["Copilot.App.exe<br/>(WPF .NET 7)"]
|
||||
L_App -->|"Native SDK<br/>(TCP direct)"| L_Srv["Camera Servers<br/>GeViScope / G-Core"]
|
||||
L_App -->|"SignalR<br/>(HTTPS/WSS)"| L_AS["AppServer<br/>(ASP.NET Core)"]
|
||||
L_AS --> L_DB["SQLite"]
|
||||
end
|
||||
|
||||
subgraph "New (Flutter)"
|
||||
N_HW["Hardware Keyboard<br/>Serial + HID"] --> N_App["Flutter App<br/>(Web/Desktop)"]
|
||||
N_App -->|"REST HTTP<br/>(localhost)"| N_Bridge["C# Bridges<br/>(.NET 8)"]
|
||||
N_Bridge -->|"Native SDK<br/>(TCP)"| N_Srv["Camera Servers<br/>GeViScope / G-Core"]
|
||||
N_App -->|"WebSocket<br/>(PRIMARY)"| N_Coord["PRIMARY Keyboard<br/>(Coordination)"]
|
||||
end
|
||||
```
|
||||
|
||||
## Component Mapping
|
||||
|
||||
| Legacy (WPF) | New (Flutter) | Notes |
|
||||
|---------------|---------------|-------|
|
||||
| `Copilot.App.exe` | `copilot_keyboard` Flutter app | Full rewrite |
|
||||
| `Copilot.Device.dll` | Web HID / Serial API | Browser APIs or native plugins |
|
||||
| `Copilot.Drivers.GeViScope.dll` | GeViScope Bridge (:7720) | SDK stays in C#, exposed via REST |
|
||||
| `Copilot.Drivers.GCore.dll` | G-Core Bridge (:7721) | SDK stays in C#, exposed via REST |
|
||||
| `Copilot.Drivers.GeviSoft.dll` | GeViServer Bridge (:7710) | SDK stays in C#, exposed via REST |
|
||||
| `Copilot.Drivers.Common.dll` | Bridge REST API contracts | Interfaces become HTTP endpoints |
|
||||
| `Copilot.AppServer.exe` | PRIMARY keyboard + WebSocket hub | **No separate server** — runs on keyboard |
|
||||
| `Copilot.AppServer.Database.dll` | In-memory state on PRIMARY | No SQLite needed |
|
||||
| `Copilot.Common.Services.dll` | `BridgeService` + `StateService` | Dart services |
|
||||
| SignalR Hub | WebSocket hub on PRIMARY | Simpler protocol |
|
||||
| `IMovementController` | `POST /api/ptz/{action}` on bridge | REST instead of direct SDK |
|
||||
| `ICameraServerDriver` | Bridge handles connection | App doesn't touch SDK |
|
||||
| `ICentralServerDriver.CrossSwitch` | `POST /api/viewer/connect-live` | Via bridge REST |
|
||||
|
||||
## Key Architectural Differences
|
||||
|
||||
### 1. SDK Access Path
|
||||
|
||||
**Legacy:** App → Native SDK DLL → Camera Server (direct TCP)
|
||||
```
|
||||
Copilot.App → GeViScopeMovementController → GscPLCWrapper → TCP → Server
|
||||
```
|
||||
|
||||
**New:** App → HTTP → C# Bridge → Native SDK → Camera Server
|
||||
```
|
||||
Flutter App → HTTP POST /api/ptz/pan → Bridge (.NET 8) → SDK → Server
|
||||
```
|
||||
|
||||
**Why:** Flutter (especially web) cannot load native .NET DLLs. The C# bridges wrap the same SDKs behind a REST API.
|
||||
|
||||
### 2. Coordination Model
|
||||
|
||||
**Legacy:** Centralized AppServer (single point of coordination)
|
||||
- All keyboards connect to one AppServer via SignalR
|
||||
- AppServer manages locks, sequences, config, alarms
|
||||
- AppServer failure = loss of coordination features
|
||||
|
||||
**New:** Distributed PRIMARY/STANDBY model
|
||||
- Any keyboard can be PRIMARY (runs coordination logic)
|
||||
- STANDBY monitors PRIMARY via heartbeat, auto-promotes after 6s
|
||||
- No separate server hardware needed
|
||||
- Critical operations (CrossSwitch, PTZ) work without PRIMARY
|
||||
|
||||
### 3. Configuration Management
|
||||
|
||||
**Legacy:** AppServer stores config → syncs to keyboards via SignalR
|
||||
**New:** `servers.json` + `keyboards.json` + `crossswitch-rules.json` loaded from local files + PRIMARY sync
|
||||
|
||||
### 4. Alarm System
|
||||
|
||||
**Legacy:** AppServer → Camea API → SignalR → Keyboards
|
||||
**New:** Each bridge can query alarms directly + periodic sync via PRIMARY
|
||||
|
||||
## Feature Parity Matrix
|
||||
|
||||
| Feature | Legacy Status | New Status | Priority |
|
||||
|---------|--------------|------------|----------|
|
||||
| CrossSwitch (camera → monitor) | Complete | Phase 1 | Critical |
|
||||
| PTZ via joystick (Pan/Tilt/Zoom) | Complete | Phase 1 | Critical |
|
||||
| Camera number entry (numpad) | Complete | Phase 1 | Critical |
|
||||
| Camera lock (PTZ coordination) | Complete | Phase 2 | High |
|
||||
| Prepositions (saved positions) | Complete | Phase 1 | High |
|
||||
| Sequences (camera cycling) | Complete | Phase 3 | Medium |
|
||||
| Function buttons (F1-F7) | Complete | Phase 1 | High |
|
||||
| Playback (jog/shuttle) | Complete | Phase 3 | Medium |
|
||||
| Alarm display | Complete | Phase 3 | Medium |
|
||||
| Alarm history | Complete | Phase 3 | Low |
|
||||
| Monitor wall segments | Complete | Phase 1 | High |
|
||||
| Config sync from server | Complete | Phase 2 | Medium |
|
||||
| Auto-update (firmware + app) | Complete | Phase 4 | Low |
|
||||
| Service menu | Complete | Phase 4 | Low |
|
||||
| Keyboard emulation (dev mode) | Complete | N/A (browser) | N/A |
|
||||
|
||||
## PTZ Speed Values: Compatible
|
||||
|
||||
The legacy app sends speed values **0-255** to the SDK. The new bridges should use the **same range** to maintain identical PTZ behavior. The zoom-proportional speed feature is provided by the camera/server infrastructure, not the app.
|
||||
|
||||
```
|
||||
Legacy: Joystick HID (-255..+255) → PanRight(speed) → SDK → Server
|
||||
New: Joystick HID (-255..+255) → POST /api/ptz/pan {speed} → Bridge → SDK → Server
|
||||
```
|
||||
|
||||
Same speed values = same camera behavior.
|
||||
|
||||
## Risk Areas
|
||||
|
||||
1. **Joystick latency** — Legacy sends joystick events directly via in-process SDK call (~1ms). New path adds HTTP overhead (~5-20ms). Monitor for responsiveness.
|
||||
2. **Lock coordination** — Legacy uses SignalR (battle-tested). New uses custom WebSocket protocol. Needs thorough testing.
|
||||
3. **Sequence execution** — Legacy runs on AppServer (always-on). New runs on PRIMARY keyboard (could failover mid-sequence).
|
||||
4. **Alarm reliability** — Legacy has Camea API integration on AppServer. New needs bridge-level alarm subscription.
|
||||
Reference in New Issue
Block a user