# API Dokumentation

Die FNA-Steuerung stellt eine REST-API bereit, über die alle Funktionen der Ampelsteuerung programmatisch abgerufen und gesteuert werden können. Die API ist unter `http://<ip-adresse>/api/` erreichbar.

---

## Übersicht der Endpunkte

<table id="bkmrk-methode-endpunkt-bes"><thead><tr><th>Methode</th><th>Endpunkt</th><th>Beschreibung</th><th class="align-center">PIN Auth</th><th class="align-center">Device Auth</th></tr></thead><tbody><tr><td>GET</td><td>`/api/status`</td><td>Aktuellen Status der Ampeln abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/cmd`</td><td>Verfügbare Befehle abrufen</td><td class="align-center">X</td><td class="align-center">X</td></tr><tr><td>POST</td><td>`/api/cmd/{cmd}`</td><td>Befehl ausführen</td><td class="align-center">X</td><td class="align-center">X</td></tr><tr><td>GET</td><td>`/api/config`</td><td>Alle Konfigurationen abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>POST</td><td>`/api/config`</td><td>Neue Konfiguration erstellen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/config/preset`</td><td>Aktive Voreinstellung abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/config/volume`</td><td>Lautstärke abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>PUT</td><td>`/api/config/volume`</td><td>Lautstärke setzen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/config/brightness`</td><td>Helligkeit abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>PUT</td><td>`/api/config/brightness`</td><td>Helligkeit setzen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>PUT</td><td>`/api/config/nach`</td><td>Nachschießen-Anzahl setzen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>DELETE</td><td>`/api/config/nach`</td><td>Nachschießen deaktivieren</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/config/{id}`</td><td>Einzelne Konfiguration abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>PUT</td><td>`/api/config/{id}`</td><td>Konfiguration aktualisieren</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>DELETE</td><td>`/api/config/{id}`</td><td>Konfiguration löschen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/logs`</td><td>Protokolleinträge abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>DELETE</td><td>`/api/logs`</td><td>Protokoll löschen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/logs/training`</td><td>Trainings-Modus abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>PUT</td><td>`/api/logs/training`</td><td>Trainings-Modus setzen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/time`</td><td>Systemzeit abrufen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>POST</td><td>`/api/sync-time`</td><td>Systemzeit synchronisieren</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>POST</td><td>`/api/auth/login`  
</td><td>Anmelden mit PIN</td><td class="align-center">  
</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/auth/status`</td><td>Status des Session (Auth)</td><td class="align-center">  
</td><td class="align-center">  
</td></tr><tr><td>POST</td><td>`/api/auth/logout`</td><td>Abmelden</td><td class="align-center">  
</td><td class="align-center">  
</td></tr><tr><td>PUT</td><td>`/api/auth/pin`</td><td>Login PIN ändern</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/devices/pending`</td><td>Liste der wartenden Geräte</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>POST</td><td>`/api/devices/pending/{device_id}/approve`</td><td>Gerät zulassen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>DELETE</td><td>`/api/devices/pending/{device_id}`</td><td>Wartendes gerät löschen</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>GET</td><td>`/api/devices/approved`</td><td>Liste der zugelassenen Geräte</td><td class="align-center">X</td><td class="align-center">  
</td></tr><tr><td>DELETE</td><td>`/api/devices/approved/{device_id}`</td><td>Zugelassenes Gerät löschen</td><td class="align-center">X</td><td class="align-center">  
</td></tr></tbody></table>

---

## Status

### `GET /api/status`

Gibt den aktuellen Betriebsstatus beider Ampeln zurück.

**Antwort** `200 OK`

```json
{
  "a1": {
    "red": true,
    "yellow": false,
    "green": false,
    "time": 120,
    "group": "A"
  },
  "a2": {
    "red": false,
    "yellow": false,
    "green": true,
    "time": 120,
    "group": "B"
  },
  "run": true,
  "group_mode": false,
  "count_arrows": 3,
  "alt_mode": false,
  "shoot_break": false,
  "shoot_off_mode": false
}

```

<table id="bkmrk-feld-typ-beschreibun"><thead><tr><th>Feld</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`a1` / `a2`</td><td>Objekt</td><td>Status von Ampel 1 und 2</td></tr><tr><td>`a1.red`</td><td>Boolean</td><td>Rotes Licht aktiv</td></tr><tr><td>`a1.yellow`</td><td>Boolean</td><td>Gelbes Licht aktiv</td></tr><tr><td>`a1.green`</td><td>Boolean</td><td>Grünes Licht aktiv</td></tr><tr><td>`a1.time`</td><td>Integer</td><td>Verbleibende Zeit in Sekunden</td></tr><tr><td>`a1.group`</td><td>String</td><td>Zugewiesene Gruppe (z. B. `"A"` oder `"B"`)</td></tr><tr><td>`run`</td><td>Boolean</td><td>Steuerung läuft aktuell</td></tr><tr><td>`group_mode`</td><td>Boolean</td><td>AB/CD-Gruppenmodus aktiv</td></tr><tr><td>`count_arrows`</td><td>Integer</td><td>Aktuell eingestellte Pfeilanzahl</td></tr><tr><td>`alt_mode`</td><td>Boolean</td><td>Alternierend-Modus aktiv</td></tr><tr><td>`shoot_break`</td><td>Boolean</td><td>Schießpause aktiv</td></tr><tr><td>`shoot_off_mode`</td><td>Boolean</td><td>Gibt an, ob Nachschießen oder Stechen eingestellt ist</td></tr></tbody></table>

---

## Befehle

### `GET /api/cmd`

Gibt zurück, welche Befehle aktuell verfügbar (ausführbar) sind.

**Antwort** `200 OK`

```json
{
  "CommandStatus": {
    "START": true,
    "STOP": false,
    "SWITCH": false,
    "BREAK": false
  }
}

```

<table id="bkmrk-befehl-beschreibung-"><thead><tr><th>Befehl</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`START`</td><td>Schießsequenz starten</td></tr><tr><td>`STOP`</td><td>Schießsequenz stoppen</td></tr><tr><td>`SWITCH`</td><td>Gruppe wechseln (bei Alternierend-Modus)</td></tr><tr><td>`BREAK`</td><td>Schießpause einleiten</td></tr></tbody></table>

---

### `POST /api/cmd/{cmd}`

Führt einen Steuerungsbefehl aus.

**Pfadparameter**

<table id="bkmrk-parameter-typ-beschr"><thead><tr><th>Parameter</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`cmd`</td><td>String</td><td>Befehl: `START`, `STOP`, `SWITCH` oder `BREAK`</td></tr></tbody></table>

**Beispiel**

```
POST /api/cmd/START
```

**Antworten**

<table id="bkmrk-code-beschreibung-20"><thead><tr><th>Code</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`200 OK`</td><td>Befehl erfolgreich ausgeführt</td></tr><tr><td>`400 Bad Request`</td><td>Ungültiger oder nicht erlaubter Befehl</td></tr><tr><td>`500 Internal Server Error`</td><td>Serverfehler</td></tr></tbody></table>

---

## Konfigurationen

Konfigurationen enthalten alle Einstellungen für einen Schießbetrieb (z. B. Zeit pro Pfeil, Pfeilanzahl, Modus). Es können mehrere Konfigurationen gespeichert werden.

### `GET /api/config`

Gibt alle gespeicherten Konfigurationen zurück.

**Antwort** `200 OK` – Array von Konfigurationsobjekten (siehe Felder unten)

---

### `POST /api/config`

Erstellt eine neue Konfiguration.

**Anfrage-Body**

```json
{
  "name": "Halle 18m",
  "time_per_arrow": 40,
  "prepare_time": 10,
  "count_arrows": 3,
  "group_mode": false,
  "alt_single": false,
  "alt_team": false
}

```

<table id="bkmrk-feld-typ-beschreibun-1"><thead><tr><th>Feld</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`name`</td><td>String</td><td>Bezeichnung der Konfiguration</td></tr><tr><td>`time_per_arrow`</td><td>Integer</td><td>Zeit pro Pfeil in Sekunden</td></tr><tr><td>`prepare_time`</td><td>Integer</td><td>Vorlaufzeit in Sekunden</td></tr><tr><td>`count_arrows`</td><td>Integer</td><td>Anzahl der Pfeile pro Durchgang</td></tr><tr><td>`group_mode`</td><td>Boolean</td><td>AB/CD-Gruppenmodus aktivieren</td></tr><tr><td>`alt_single`</td><td>Boolean</td><td>Alternierend Einzeln aktivieren</td></tr><tr><td>`alt_team`</td><td>Boolean</td><td>Alternierend Mannschaft aktivieren</td></tr></tbody></table>

**Antwort** `200 OK` – Die erstellte Konfiguration inkl. `id` und `preset`-Flag

---

### `GET /api/config/{id}`

Gibt eine einzelne Konfiguration anhand ihrer ID zurück.

---

### `PUT /api/config/{id}`

Aktualisiert eine vorhandene Konfiguration. Body entspricht `POST /api/config`.

---

### `DELETE /api/config/{id}`

Löscht eine Konfiguration anhand ihrer ID.

---

### `GET /api/config/preset`

Gibt die aktuell als Voreinstellung markierte Konfiguration zurück.

**Antworten**

<table id="bkmrk-code-beschreibung-20-1"><thead><tr><th>Code</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`200 OK`</td><td>Voreinstellung gefunden</td></tr><tr><td>`404 Not Found`</td><td>Keine Voreinstellung gesetzt</td></tr></tbody></table>

---

## Lautstärke &amp; Helligkeit

### `GET /api/config/volume`

Gibt die aktuelle Lautstärke der Hupe zurück.

**Antwort** `200 OK`

```json
{ "amp_horn_vol": 80 }

```

---

### `PUT /api/config/volume?vol={wert}`

Setzt die Lautstärke der Hupe.

**Abfrageparameter**

<table id="bkmrk-parameter-typ-pflich"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`vol`</td><td>Integer</td><td>Ja</td><td>Lautstärkewert</td></tr></tbody></table>

---

### `GET /api/config/brightness`

Gibt die aktuelle Helligkeit der Ampeln zurück.

**Antwort** `200 OK`

```json
{ "amp_bright": 100 }

```

---

### `PUT /api/config/brightness?bright={wert}`

Setzt die Helligkeit der Ampeln.

<table id="bkmrk-parameter-typ-pflich-1"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`bright`</td><td>Integer</td><td>Ja</td><td>Helligkeitswert</td></tr></tbody></table>

---

## Nachschießen

### `PUT /api/config/nach?count={anzahl}`

Aktiviert das Nachschießen mit der angegebenen Pfeilanzahl. Bei Alternierendem Modus wird hiermit das Stecken mit angegebener Schützenzahl aktiviert.

<table id="bkmrk-parameter-typ-pflich-2"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`count`</td><td>Integer</td><td>Ja</td><td>Anzahl der Pfeile für das Nachschießen / Schützen für Stechen</td></tr></tbody></table>

---

### `DELETE /api/config/nach`

Deaktiviert das Nachschießen.

---

## Protokoll (Logs)

### `GET /api/logs`

Gibt alle Protokolleinträge zurück.

**Antwort** `200 OK`

```json
[
  {
    "id": 1,
    "timestamp": "2026-04-03T10:00:00",
    "action": "START",
    "description": "Schießsequenz gestartet"
  }
]

```

<table id="bkmrk-feld-typ-beschreibun-2"><thead><tr><th>Feld</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`id`</td><td>Integer</td><td>Eindeutige ID des Eintrags</td></tr><tr><td>`timestamp`</td><td>DateTime</td><td>Zeitstempel des Ereignisses</td></tr><tr><td>`action`</td><td>String</td><td>Ausgeführte Aktion</td></tr><tr><td>`description`</td><td>String</td><td>Beschreibung des Ereignisses</td></tr></tbody></table>

---

### `DELETE /api/logs`

Löscht alle Protokolleinträge.

---

### `GET /api/logs/training`

Gibt zurück, ob der Trainings-Modus aktiv ist (Protokolleinträge werden im Trainings-Modus nicht für das Schießleiterprotokoll gewertet).

**Antwort** `200 OK`

```json
{ "training": false }

```

---

### `PUT /api/logs/training?training={wert}`

Aktiviert oder deaktiviert den Trainings-Modus.

<table id="bkmrk-parameter-typ-pflich-3"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Standard</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`training`</td><td>Boolean</td><td>Nein</td><td>`false`</td><td>`true` = Trainings-Modus aktiv</td></tr></tbody></table>

---

## Zeit

### `GET /api/time`

Gibt die aktuelle Systemzeit der Steuerung zurück.

**Antwort** `200 OK`

```json
{ "time": "2026-04-03T10:00:00" }

```

---

### `POST /api/sync-time`

Synchronisiert die Systemzeit der Steuerung.

**Anfrage-Body**

```json
{ "time": "2026-04-03T10:00:00" }

```

**Antwort** `200 OK` – Bestätigung mit der gesetzten Zeit

---

## Auth

### `POST /api/auth/login`

Authentifiziert die UI

**Anfrage-Body**

```json
{ "pin": "123456" }

```

**Antwort** `200 OK`

```json
{  "token": "AA-BB-CC-DD" }

```

### `GET /api/auth/status`

Gibt den Auth Status zurück

**Antwort** `200 OK`

```json
{  "authenticated": true }

```

### `POST /api/auth/logout`

Meldet die Session ab

**Antwort** `200 OK`

### `POST /api/auth/pin`

Änder die Anmeldepin

**Anfrage-Body**

```json
{ "new_pin": "987654" }

```

**Antwort** `200 OK`

---

## Devices

### `GET /api/devices/pending`

Gibt eine Liste der wartenden Geräte zurück

**Antwort** `200 OK`

```json
[
  {
    "id": 1,
    "ip": "192.168.1.10",
    "first_seen": "2026-04-27T15:02:44.310Z",
    "last_seen": "2026-04-27T15:02:44.310Z",
    "request_count": 5,
    "app_name": "amp",
    "device_type": "remote",
    "discover_checked": true
  }
]

```

<table id="bkmrk-feld-typ-beschreibun-3"><thead><tr><th>Feld</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`id`</td><td>Integer</td><td>Eindeutige ID des Eintrags</td></tr><tr><td>`ip`</td><td>String</td><td>IP des Gerätes</td></tr><tr><td>`first_seen`</td><td>TimeStamp</td><td>Wann hat sich das Gerät zum ersten mal gemeldet</td></tr><tr><td>`last_seen`</td><td>TimeStamp</td><td>Wann hat sich das Gerät zum letzten mal gemeldet</td></tr><tr><td>`request_count`</td><td>Integer</td><td>Wie oft hat sich das Gerät gemeldet</td></tr><tr><td>`app_name`</td><td>String</td><td>Info aus dem /discover feld App (Wenn vorhanden)</td></tr><tr><td>`device_type`</td><td>String</td><td>Info aus dem /discover feld Type (Wenn vorhanden)</td></tr><tr><td>`discover_checked`</td><td>Boolean</td><td>Gibt an, ob /discover geprüft werden konnte</td></tr></tbody></table>


### `POST /api/devices/pending/{device_id}/approve`

Gibt ein Gerät anhand der device\_id frei, sodass dieses die Ampel steuern kann.

**Abfrageparameter**

<table id="bkmrk-parameter-typ-pflich-4"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`device_id`</td><td>Integer</td><td>Ja</td><td>Device ID</td></tr></tbody></table>

**Antwort** `200 OK`

### `DELETE /api/devices/pending/{device_id}`

Weist ein wartendes Gerät zurück anhand der device\_id.

**Abfrageparameter**

<table id="bkmrk-parameter-typ-pflich-5"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`device_id`</td><td>Integer</td><td>Ja</td><td>Device ID</td></tr></tbody></table>

**Antwort** `200 OK`

### `GET /api/devices/approved`

Gibt eine Liste der zugelassenen Geräte zurück

**Antwort** `200 OK`

```json
[
  {
    "id": 1,
    "ip": "192.168.1.10",
    "app_name": "amp",
    "device_type": "remote",
    "approved_at": "2026-04-27T15:13:04.210Z",
    "expires_at": "2026-04-27T15:13:04.210Z"
  }
]

```

<table id="bkmrk-feld-typ-beschreibun-4"><thead><tr><th>Feld</th><th>Typ</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`id`</td><td>Integer</td><td>Eindeutige ID des Eintrags</td></tr><tr><td>`ip`</td><td>String</td><td>IP des Gerätes</td></tr><tr><td>`app_name`</td><td>String</td><td>Info aus dem /discover feld App (Wenn vorhanden)</td></tr><tr><td>`device_type`</td><td>String</td><td>Info aus dem /discover feld Type (Wenn vorhanden)</td></tr><tr><td>`approved_at`</td><td>TimeStamp</td><td>Gibt an, wann das Gerät zugelassen wurde</td></tr><tr><td>`expires_at`</td><td>TimeStamp</td><td>Gibt an, ab wann das Gerät nicht mehr zugelassen ist</td></tr></tbody></table>

### `DELETE /api/devices/approved/{device_id}`

Weist ein zugelassenes Gerät zurück anhand der device\_id. Dannach ist das Gerät nicht mehr berechtigt Anfragen an `/api/cmd` zu senden

**Abfrageparameter**

<table id="bkmrk-parameter-typ-pflich-6"><thead><tr><th>Parameter</th><th>Typ</th><th>Pflicht</th><th>Beschreibung</th></tr></thead><tbody><tr><td>`device_id`</td><td>Integer</td><td>Ja</td><td>Device ID</td></tr></tbody></table>

**Antwort** `200 OK`

---

## Antwortformate

### Erfolg / Fehler (`DefaultStatusOUT`)

Viele Endpunkte antworten bei Erfolg oder Fehler mit folgendem Format:

```json
{ "status": "ok" }

```

---

## Hinweise

> **Wichtig:** Im Netzwerk darf nur eine Steuerung gleichzeitig laufen, da sonst die Anzeigegeräte widersprüchliche Informationen erhalten könnten.

- Alle Zeitangaben im Format ISO 8601 (`YYYY-MM-DDTHH:MM:SS`)
- Die API ist nur durch eine PIN Authentifizierung gesichert – sie sollte nur in einem gesicherten, lokalen Netzwerk betrieben werden
- Basis-URL: `http://<ip-adresse>/api/`