--- title: "AppServer" description: "ASP.NET Core coordination server - SignalR hub, REST API, database, admin UI" --- # AppServer (Copilot.AppServer) The AppServer is a centralized coordination service that runs as an ASP.NET Core application (Windows Service capable). It does NOT handle video — only coordination between keyboards. ## Architecture ```mermaid graph TB subgraph "Copilot.AppServer.exe" subgraph "SignalR Hub" CamLock["Camera Lock
Management"] SeqMgr["Sequence
Scheduler"] CfgSync["Configuration
Sync"] ViewState["Viewer State
Broadcasting"] AlarmQ["Alarm Query
Proxy"] end subgraph "REST API (v1)" Updates["GET /api/v1/updates/{name}
Auto-update manifest"] CfgAPI["Configuration endpoints"] end subgraph "Blazor Admin UI" AdminWWW["Web-based admin panel
Configuration management"] end subgraph "Database" SQLite["SQLite (copilot.db)
• Camera locks
• Lock history
• Alarm cache"] end subgraph "External Integrations" CameaClient["Camea API Client
http://localhost:8081
Alarm data source"] end end K1["Keyboard 1"] -->|WSS| CamLock K2["Keyboard 2"] -->|WSS| SeqMgr K3["Keyboard 3"] -->|WSS| CfgSync CamLock --> SQLite AlarmQ --> CameaClient AdminWWW --> CfgSync ``` ## SignalR Hub Interface The hub exposes methods grouped by function: ### Camera Locks ``` TryLockCamera(cameraId, copilotName, priority) → CameraLockResult UnlockCamera(cameraId, copilotName) RequestCameraLock(cameraId, copilotName, priority) CameraLockConfirmTakeOver(cameraId, copilotName, confirm) ResetCameraLockExpiration(cameraId, copilotName) GetLockedCameraIds(copilotName) → IEnumerable ``` ### Camera Lock Notifications (Server → Client) ``` CameraLockNotify(notification) where notification has: - NotificationType: Acquired | TakenOver | ConfirmTakeOver | Confirmed | Rejected | ExpireSoon | Unlocked - CameraId: int - CopilotName: string ``` ### Sequences ``` Start(viewerId, sequenceId) Stop(viewerId) GetSequences(categoryId) → IEnumerable GetSequenceCategories() → IEnumerable GetRunningSequences() → IEnumerable ``` ### Sequence Notifications (Server → Client) ``` ViewerSequenceStateChanged(ViewerSequenceState) ``` ### Configuration ``` GetConfigurationFile(filename) → ConfigurationFile ``` ### Configuration Notifications (Server → Client) ``` ConfigurationFileChanged(ConfigurationFile) ``` ### Alarms ``` GetCamerasWithAlarms() → HashSet GetAlarmsForCamera(cameraId, from, to) → IReadOnlyList ``` ## Database Schema (SQLite) Managed via Entity Framework Core with code-first migrations: ```mermaid erDiagram CameraLock { int CameraId PK string OwnerName string Priority datetime ExpiresAt datetime CreatedAt } CameraLockHistory { int Id PK int CameraId string OwnerName string Action datetime Timestamp } AlarmCache { int Id PK int CameraId int AlarmTypeId string Name datetime StartTime datetime EndTime } ``` ## Lock Expiration System ```mermaid graph TD Lock["Lock Created
(ExpiresAt = now + 5min)"] --> Timer["Expiration Timer"] Timer -->|"T+4min
(1min before expiry)"| Warn["Send ExpireSoon
notification"] Warn --> Reset{"PTZ Action?"} Reset -->|Yes| ExtendLock["Reset ExpiresAt = now + 5min"] ExtendLock --> Timer Reset -->|No timeout| Expire["Send Unlocked
notification"] Expire --> Remove["Remove lock from DB"] ``` ## Auto-Update System The AppServer serves firmware and application updates: ``` GET /api/v1/updates/{copilotName} → Returns JSON array of available updates: [ { "Version": "1.0.706", "Url": "https://copilot.test.d6.colsys.cz/updates/Copilot-1.0.706.zip", "Changelog": "https://...", "Mandatory": { "Value": true, "MinVersion": "1.0.700" }, "CheckSum": { "Value": "abc123...", "HashingAlgorithm": "SHA256" } } ] ``` The WPF app uses `AutoUpdater.NET` to check on startup and apply updates. ## Deployment ``` Copilot.AppServer.exe ├── appsettings.json (main config) ├── configs/ │ ├── appsettings-copilot.json │ ├── appsettings-camera-servers.json │ ├── appsettings-monitor-wall.json │ ├── appsettings-function-buttons.json │ ├── appsettings-prepositions.json │ ├── appsettings-sequences.json │ └── appsettings-sequence-categories.json ├── copilot.db (SQLite database) ├── wwwroot/ (Blazor admin UI assets) ├── logs/ │ ├── copilot-appserver-YYYYMMDD.log │ └── buffer/ (Elasticsearch buffer) └── web.config (IIS hosting, if used) ``` Runs as: - Windows Service (`Microsoft.Extensions.Hosting.WindowsServices`) - Or standalone Kestrel server on HTTPS port 443 - Uses machine certificate store for TLS