---
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