Files
COPILOT/Docs/legacy-architecture/migration-comparison.md
klas 40143734fc 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>
2026-02-12 14:57:38 +01:00

5.5 KiB

title, description
title description
Legacy → Flutter Migration Comparison Side-by-side comparison of legacy WPF architecture vs new Flutter system

Legacy → Flutter Migration Comparison

Architecture Comparison

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.