---
title: "Configuration"
description: "JSON configuration files, monitor wall topology, and function button mapping"
---

# Configuration System

## Configuration Files

All configuration is stored as JSON files, managed centrally on the AppServer and synced to each keyboard.

### appsettings.json (Main)

```json
{
    "UseSoftwareRendering": true,
    "AppServerConfiguration": {
        "Uri": "https://copilot.test.d6.colsys.cz",
        "Timeout": "00:00:01.5"
    },
    "ReconnectionConfiguration": {
        "ReconnectionPeriod": "00:00:02"
    },
    "ViewerStates": {
        "AppServerConnectionTimeout": "00:00:05"
    }
}
```

| Setting | Value | Purpose |
|---------|-------|---------|
| `UseSoftwareRendering` | `true` | Forces WPF software rendering (no GPU) for LattePanda |
| `AppServerConfiguration.Uri` | HTTPS URL | Central AppServer for coordination |
| `AppServerConfiguration.Timeout` | 1.5s | HTTP request timeout |
| `ReconnectionPeriod` | 2s | Auto-reconnect interval to camera servers |
| `AppServerConnectionTimeout` | 5s | SignalR connection timeout |

### appsettings-copilot.json (Per-Keyboard)

```json
{
    "CopilotConfig": {
        "WallId": 2,
        "CameraLockOptions": {
            "Priority": "Low",
            "Timeout": "00:05:00"
        },
        "CameraNumberOptions": {
            "MaxLength": 6,
            "Prefixes": ["500", "501", "502"],
            "CancelEditTimeout": "00:05"
        },
        "ViewerStateThrottleInterval": "00:00:00.150",
        "CentralServer": {
            "IpAddress": "192.168.102.186",
            "UserName": "sysadmin",
            "Password": "masterkey"
        },
        "AllowPrepositionsInterval": {
            "Min": 10,
            "Max": 99
        },
        "PlaybackOptions": {
            "Allowed": true,
            "Speeds": [1, 2, 5, 15, 30, 100, 250]
        },
        "AlarmHistoryOptions": {
            "CameraIdExtractionRegex": "^\\D*(?<CameraId>\\d{6})\\D*$",
            "DefaultSearchInterval": "30.00:00:00"
        }
    }
}
```

| Setting | Purpose |
|---------|---------|
| `WallId` | Which monitor wall this keyboard controls |
| `CameraLockOptions.Priority` | PTZ lock priority (`Low` / `High`) |
| `CameraLockOptions.Timeout` | Lock auto-expiration (5 min) |
| `CameraNumberOptions.MaxLength` | Max digits for camera number (6) |
| `CameraNumberOptions.Prefixes` | Auto-prefixes for camera numbers |
| `CancelEditTimeout` | Auto-cancel camera number entry (5 sec) |
| `ViewerStateThrottleInterval` | Debounce viewer state updates (150ms) |
| `PlaybackOptions.Speeds` | Shuttle playback speeds (1x to 250x) |
| `AllowPrepositionsInterval` | Valid preposition range (10-99) |

### appsettings-camera-servers.json

```json
{
    "CameraServerConfig": {
        "CameraServers": [
            {
                "IpAddress": "192.168.102.20",
                "UserName": "sysadmin",
                "Password": "masterkey",
                "CameraServerType": "GCore"
            },
            {
                "IpAddress": "192.168.102.186",
                "UserName": "sysadmin",
                "Password": "masterkey",
                "CameraServerType": "GeviScope"
            }
        ]
    }
}
```

Supported server types: `GeViScope`, `GCore`, `GeViSoft`

### appsettings-monitor-wall.json (Topology)

Defines the physical monitor wall layout:

```mermaid
graph TD
    subgraph "Wall (WallId: 1, Name: HDŘÚ TSK/DIC)"
        subgraph "Segment 1 (4 rows × 8 cols)"
            M1["Monitor #01<br/>2×2 span<br/>VM: 151,152,153,154"]
            M2["Monitor #02<br/>2×2 span<br/>VM: 155,156,157,158"]
            M3["Monitor #03"]
            M4["Monitor #04"]
            M5["Monitor #05<br/>...etc"]
        end
    end
```

Hierarchy:
```
Wall
  └── Segment (grid: RowCount × ColumnCount)
        └── Monitor (physical screen, positioned at Row/Col with RowSpan/ColSpan)
              └── VirtualMonitor (individual video feed, positioned within monitor grid)
```

A single physical monitor can display multiple virtual monitors (e.g., 2×2 quad view). Each VirtualMonitor has a unique `VirtualMonitorId` that maps to a `ViewerId` in the camera server.

### appsettings-function-buttons.json

Maps F1-F7 and Home keys to actions per wall:

```json
{
    "FunctionButtonsConfig": {
        "FunctionButtons": [
            {
                "WallId": 1,
                "Buttons": [
                    {
                        "Button": "F1",
                        "Actions": [
                            { "ViewerId": 1001, "ActionType": "CrossSwitch", "SourceId": 501111 },
                            { "ViewerId": 1002, "ActionType": "CrossSwitch", "SourceId": 502345 }
                        ]
                    },
                    {
                        "Button": "F4",
                        "Actions": [
                            { "ViewerId": 1001, "ActionType": "SequenceStart", "SourceId": 258 }
                        ]
                    }
                ]
            }
        ]
    }
}
```

Action types: `CrossSwitch` (switch camera to viewer), `SequenceStart` (start camera cycling)

### appsettings-sequences.json

```json
{
    "SequencesConfig": {
        "Sequences": [
            {
                "Id": 1,
                "CategoryId": 1,
                "Name": "Test-A",
                "Interval": 1,
                "MediaChannels": [500100, 500101, 500102, 500103]
            }
        ]
    }
}
```

## AppServer Configuration

```json
{
    "ConnectionStrings": {
        "SqliteConnection": "Data Source=copilot.db"
    },
    "CameaApiClient": {
        "Uri": "http://localhost:8081",
        "Timeout": "00:00:01.5",
        "TimeZone": "Central Europe Standard Time"
    },
    "LockExpirationConfig": {
        "LockExpirationTimeout": "00:05:00",
        "NotificationBeforeExpiration": "00:01:00"
    },
    "Kestrel": {
        "Endpoints": {
            "Https": {
                "Url": "https://*:443",
                "Certificate": {
                    "Subject": "copilot.test.d6.colsys.cz",
                    "Store": "Root",
                    "Location": "LocalMachine"
                }
            }
        }
    }
}
```

## Network Topology

```
┌───────────────────────────────────────────────────────────┐
│                    192.168.102.0/24 Network                │
│                                                            │
│  ┌─────────────────┐  ┌─────────────────┐                │
│  │ GeViScope Server │  │ G-Core Server   │                │
│  │ 192.168.102.186  │  │ 192.168.102.20  │                │
│  │ sysadmin/master  │  │ sysadmin/master  │                │
│  └────────┬─────────┘  └────────┬────────┘                │
│           │ TCP (native SDK)     │ TCP (native SDK)        │
│           │                      │                         │
│  ┌────────┴──────────────────────┴────────┐               │
│  │              Keyboard SBC               │               │
│  │        (LattePanda Sigma)               │               │
│  │  Copilot.App.exe (WPF)                 │               │
│  └────────┬───────────────────────────────┘               │
│           │ HTTPS/WSS (SignalR)                            │
│           │                                                │
│  ┌────────┴───────────────────────────────┐               │
│  │         AppServer                       │               │
│  │  copilot.test.d6.colsys.cz:443        │               │
│  │  Copilot.AppServer.exe                 │               │
│  │  + SQLite DB + Camea API (:8081)       │               │
│  └────────────────────────────────────────┘               │
│                                                            │
│  ┌────────────────────────────────────────┐               │
│  │  Elasticsearch (logging)               │               │
│  │  localhost:9200                         │               │
│  └────────────────────────────────────────┘               │
└───────────────────────────────────────────────────────────┘
```
