Files
COPILOT/Docs/legacy-architecture/architecture.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

7.2 KiB

title, description
title description
System Architecture Component diagrams, dependency graph, and deployment model

System Architecture

Component Dependency Graph

graph TB
    subgraph "Copilot.App.exe (WPF Client)"
        App["App.cs<br/>.NET Generic Host"]
        MW["MainWindow<br/>Input Router"]
        SVM["SegmentViewModel<br/>Main Screen Logic"]
        PVM["PlaybackViewModel"]
        CSVM["CameraSearchViewModel"]
        PreVM["PrepositionsViewModel"]
        SeqVM["SequenceCategoriesViewModel<br/>SequencesViewModel"]
        SvcVM["ServiceMenuViewModel"]

        subgraph "App Services"
            CCS["CameraControllerService"]
            CLS["CameraLockService"]
            CAS["CameraAlarmService"]
            SeqS["SequenceService"]
            FBS["FunctionButtonsService"]
            PBS["PlaybackStateService"]
            CfgS["ConfigurationService"]
            NAS["NetworkAvailabilityState"]
        end

        subgraph "Navigation"
            NS["NavigationService"]
            NStore["NavigationStore"]
        end
    end

    subgraph "Copilot.Device.dll"
        CD["CopilotDevice"]
        SP["SerialPortDataProvider"]
        HID["JoystickHidDataProvider"]
    end

    subgraph "Copilot.Common.dll"
        Config["Configuration System"]
        Hub["ICopilotHub<br/>ICopilotHubEvents"]
        Prov["ICopilotInfoProvider"]
    end

    subgraph "Copilot.Common.Services.dll"
        MCS["MediaChannelService"]
        VSS["ViewerStateService"]
        CSDP["CameraServerDriverProvider"]
        CenDP["CentralServerDriverProvider"]
    end

    subgraph "Copilot.Drivers.Common.dll"
        IMC["IMovementController"]
        ICSD["ICameraServerDriver"]
        ICenD["ICentralServerDriver"]
        IVC["IViewerController"]
    end

    subgraph "Copilot.Drivers.GeViScope.dll"
        GscD["GeViScopeDriver"]
        GscMC["GeViScopeMovementController"]
        GscVC["GeviScopeViewerController"]
    end

    subgraph "Copilot.Drivers.GCore.dll"
        GcD["GCoreDriver"]
        GcMC["GCoreMovementController"]
        GcVC["GCoreViewerController"]
    end

    subgraph "Copilot.AppServer.Client.dll"
        ASC["AppServerClient<br/>(SignalR)"]
        Avail["AvailabilityState"]
    end

    App --> MW
    MW --> CD
    MW --> SVM
    SVM --> CCS
    SVM --> CLS
    SVM --> FBS
    SVM --> CAS
    CLS --> Hub
    CAS --> Hub
    SeqS --> Hub
    CfgS --> Hub
    CCS --> CSDP
    CCS --> MCS
    CSDP --> GscD
    CSDP --> GcD
    CenDP --> GscD
    GscD --> GscMC
    GscD --> GscVC
    GcD --> GcMC
    GcD --> GcVC
    GscMC -.->|implements| IMC
    GcMC -.->|implements| IMC
    GscD -.->|implements| ICSD
    GcD -.->|implements| ICSD
    Hub --> ASC

Service Lifetime & Registration

All services are registered via Microsoft.Extensions.DependencyInjection in App.cs:

graph LR
    subgraph "Singletons (one instance)"
        MainWindow
        SegmentViewModel
        NavigationStore
        NavigationService
        CameraLockService
        PlaybackStateService
        ConfigurationService
        CameraAlarmService
        CameraControllerService
        PrepositionService
        SequenceService
        NetworkAvailabilityState
    end

    subgraph "Transient (new per request)"
        CameraSearchViewModel
        PlaybackViewModel
        PrepositionsViewModel
        SequenceCategoriesViewModel
        SequencesViewModel
        ServiceMenuViewModel
        ErrorViewModel
        CameraAlarmHistoryViewModel
    end

    subgraph "Hosted Services (background workers)"
        StartupConfigurationCheckWorker
        ViewerStatesInitWorker
        CameraAlarmsUpdateWorker
        NetworkAvailabilityWorker
        SequenceService_Hosted["SequenceService<br/>(also IHostedService)"]
        ProcessMonitorServiceHost
    end

Startup Sequence

sequenceDiagram
    participant App as App.cs
    participant Host as .NET Host
    participant MW as MainWindow
    participant Nav as NavigationService
    participant Device as CopilotDevice
    participant Hub as SignalR Hub
    participant Config as ConfigurationService

    App->>Host: Build & ConfigureServices
    Host->>Host: Register all DI services
    App->>Host: StartAsync()
    Host->>Host: Start background workers

    Note over Host: StartupConfigurationCheckWorker starts
    Note over Host: ViewerStatesInitWorker starts
    Note over Host: CameraAlarmsUpdateWorker starts
    Note over Host: NetworkAvailabilityWorker starts

    App->>Nav: Navigate<SegmentsPage>(wallId)
    App->>MW: Show()
    MW->>Device: Subscribe JoystickMoved
    MW->>Device: Subscribe VirtualKeyDown/Up

    alt Firmware outdated
        MW->>Nav: Navigate<UpdateFirmwarePage>
    end

    App->>Config: UpdateAllConfigurationsIfChanged()
    Config->>Hub: GetConfigurationFile() for each manager
    Config->>Config: Write updated configs to disk

    Note over App: Application Ready

Navigation System

The app uses a custom stack-based navigation system (not WPF Navigation):

stateDiagram-v2
    [*] --> SegmentsPage: Initial (select segment)
    SegmentsPage --> SegmentPage: Select segment

    SegmentPage --> CameraSearchPage: Search button
    SegmentPage --> PrepositionsPage: Prepositions button
    SegmentPage --> PlaybackPage: Playback button
    SegmentPage --> SequenceCategoriesPage: Sequence button
    SegmentPage --> CameraAlarmHistoryPage: Alarm history
    SegmentPage --> ServiceMenuPage: Hold Backspace 3s
    SegmentPage --> CameraLockExpirationView: Lock expiring

    CameraSearchPage --> SegmentPage: Back
    PrepositionsPage --> PrepositionAddPage: Add preset
    PrepositionAddPage --> PrepositionsPage: Back
    PrepositionsPage --> SegmentPage: Back
    PlaybackPage --> SegmentPage: Back
    SequenceCategoriesPage --> SequencesPage: Select category
    SequencesPage --> SegmentPage: Start sequence

    ServiceMenuPage --> UpdateFirmwarePage: Update firmware

Two Communication Paths

The app communicates with two distinct backends simultaneously:

Path 1: Direct SDK (Camera Operations)

App → CameraServerDriverProvider → GeViScope/GCore Driver → Native SDK → Camera Server
  • Used for: CrossSwitch, PTZ, Playback, Viewer control
  • Latency: < 50ms (direct TCP connection to camera server)
  • Reconnection: Automatic, 2-second retry interval

Path 2: SignalR Hub (Coordination)

App → CopilotHub (SignalR) → AppServer → Database/Logic → Response
  • Used for: Camera locks, sequences, config sync, alarm history, viewer state
  • Latency: ~100-200ms (HTTPS + server processing)
  • Reconnection: Automatic via SignalR reconnection policy
graph LR
    subgraph "App"
        SVM["SegmentViewModel"]
    end

    subgraph "Path 1: Direct (low latency)"
        Driver["GeViScope/GCore Driver"]
        SDK["Native SDK (TCP)"]
    end

    subgraph "Path 2: Coordinated"
        HubC["SignalR Client"]
        HTTPS["HTTPS/WSS"]
    end

    subgraph "Camera Server"
        CS["GeViScope / G-Core"]
    end

    subgraph "AppServer"
        HubS["SignalR Hub"]
        DB["SQLite DB"]
    end

    SVM -->|"CrossSwitch, PTZ,<br/>Playback"| Driver
    Driver --> SDK --> CS

    SVM -->|"Locks, Sequences,<br/>Config, Alarms"| HubC
    HubC --> HTTPS --> HubS
    HubS --> DB