--- title: "System Architecture" description: "Component diagrams, dependency graph, and deployment model" --- # System Architecture ## Component Dependency Graph ```mermaid graph TB subgraph "Copilot.App.exe (WPF Client)" App["App.cs
.NET Generic Host"] MW["MainWindow
Input Router"] SVM["SegmentViewModel
Main Screen Logic"] PVM["PlaybackViewModel"] CSVM["CameraSearchViewModel"] PreVM["PrepositionsViewModel"] SeqVM["SequenceCategoriesViewModel
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
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
(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`: ```mermaid 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
(also IHostedService)"] ProcessMonitorServiceHost end ``` ## Startup Sequence ```mermaid 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(wallId) App->>MW: Show() MW->>Device: Subscribe JoystickMoved MW->>Device: Subscribe VirtualKeyDown/Up alt Firmware outdated MW->>Nav: Navigate 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): ```mermaid 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 ```mermaid 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,
Playback"| Driver Driver --> SDK --> CS SVM -->|"Locks, Sequences,
Config, Alarms"| HubC HubC --> HTTPS --> HubS HubS --> DB ```