repeater/openapi.yaml
Pierre-Olivier Mercier 950f73371c station: Surface signal, traffic and connection time in API and UI
Hostapd already parsed signal strength and rx/tx counters but the
station -> ConnectedDevice conversion threw them away. Add signalDbm,
rxBytes, txBytes and connectedAt to the OpenAPI schema and the
ConnectedDevice model, and centralise the conversion in
station.ToConnectedDevice so handlers, the periodic refresh and the
event callbacks all serialise the same shape.

Two follow-on bugs surfaced while wiring this up:

- The hostapd backend only stored station entries on first contact.
  Subsequent polls were dropped, so signal and byte counters never
  refreshed. Reconcile updates in checkStationChanges.
- ConnectedAt was reset to time.Now() on every conversion. Track
  FirstSeen on HostapdStation when the station joins, and preserve
  the timestamp across periodic refreshes in app.go so the UI's
  "connected since" badge is stable.

Frontend gains a metrics row on each device card with signal bars,
total traffic and a live duration. Falls back gracefully when a
backend (DHCP, ARP) doesn't expose these fields.
2026-05-01 22:26:43 +08:00

576 lines
16 KiB
YAML

openapi: 3.0.3
info:
title: Travel Router Control API
description: |
API for controlling a mini travel router with dual WiFi interfaces and Ethernet connectivity.
The router can operate as a WiFi repeater, connecting to upstream networks while providing
a hotspot for client devices.
version: 1.0.0
contact:
name: API Support
license:
name: MIT
servers:
- url: http://localhost:8080
description: Local router API
tags:
- name: WiFi
description: WiFi client operations (upstream network connection)
- name: Hotspot
description: Access point operations (client-facing hotspot)
- name: Devices
description: Connected devices management
- name: System
description: System status and monitoring
- name: Logs
description: System logs and real-time monitoring
paths:
/api/wifi/networks:
get:
tags:
- WiFi
summary: Get discovered WiFi networks
description: |
Returns the list of WiFi networks from the last scan without triggering a new scan.
Returns an empty list if no scan has been performed yet.
operationId: getWiFiNetworks
responses:
'200':
description: List of discovered networks
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/WiFiNetwork'
example:
- ssid: "Hotel-Guest"
signal: 5
security: "WPA2"
channel: 6
bssid: "aa:bb:cc:dd:ee:ff"
- ssid: "Public-WiFi"
signal: 3
security: "Open"
channel: 11
bssid: "11:22:33:44:55:66"
'500':
description: Error retrieving networks
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/wifi/scan:
get:
tags:
- WiFi
summary: Scan for available WiFi networks
description: |
Triggers a WiFi scan using wpa_supplicant via D-Bus and returns all discovered networks
sorted by signal strength. The scan takes approximately 2 seconds to complete.
operationId: scanWiFi
responses:
'200':
description: Successfully scanned networks
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/WiFiNetwork'
example:
- ssid: "Hotel-Guest"
signal: 5
security: "WPA2"
channel: 6
bssid: "aa:bb:cc:dd:ee:ff"
- ssid: "Public-WiFi"
signal: 3
security: "Open"
channel: 11
bssid: "11:22:33:44:55:66"
'500':
description: Scan error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/wifi/connect:
post:
tags:
- WiFi
summary: Connect to a WiFi network
description: |
Connects the router to an upstream WiFi network using wpa_supplicant.
Supports both open and password-protected networks (WPA/WPA2).
operationId: connectWiFi
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/WiFiConnectRequest'
examples:
protected:
summary: WPA2 protected network
value:
ssid: "Hotel-Guest"
password: "guest1234"
open:
summary: Open network
value:
ssid: "Public-WiFi"
password: ""
responses:
'200':
description: Successfully connected
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
'400':
description: Invalid request data
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Connection failed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/wifi/disconnect:
post:
tags:
- WiFi
summary: Disconnect from WiFi network
description: |
Disconnects from the currently connected upstream WiFi network
and removes all saved network configurations.
operationId: disconnectWiFi
responses:
'200':
description: Successfully disconnected
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
'500':
description: Disconnection failed
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/hotspot/toggle:
post:
tags:
- Hotspot
summary: Toggle hotspot on/off
description: |
Enables or disables the hotspot (access point) by starting/stopping
the hostapd service. Returns the new enabled state and updates
the system status with current hostapd_cli information.
operationId: toggleHotspot
responses:
'200':
description: Hotspot state changed successfully
content:
application/json:
schema:
type: object
properties:
enabled:
type: boolean
description: Current hotspot state after toggle
required:
- enabled
example:
enabled: true
'500':
description: Failed to change hotspot state
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/devices:
get:
tags:
- Devices
summary: Get connected devices
description: |
Returns a list of all devices currently connected to the hotspot.
Device information is gathered from DHCP leases and ARP tables.
Only devices with active ARP entries are considered connected.
operationId: getDevices
responses:
'200':
description: List of connected devices
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/ConnectedDevice'
example:
- name: "iPhone-12"
type: "mobile"
mac: "aa:bb:cc:11:22:33"
ip: "192.168.1.100"
- name: "MacBook-Pro"
type: "laptop"
mac: "dd:ee:ff:44:55:66"
ip: "192.168.1.101"
'500':
description: Failed to retrieve device list
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/api/status:
get:
tags:
- System
summary: Get system status
description: |
Returns comprehensive system status including WiFi connection state,
detailed hotspot status from hostapd_cli, connected device count,
data usage, and uptime.
operationId: getStatus
responses:
'200':
description: Current system status
content:
application/json:
schema:
$ref: '#/components/schemas/SystemStatus'
/api/logs:
get:
tags:
- Logs
summary: Get system logs
description: |
Returns the last 100 log entries from the system.
For real-time log streaming, use the WebSocket endpoint.
operationId: getLogs
responses:
'200':
description: List of log entries
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/LogEntry'
example:
- timestamp: "2025-10-28T14:32:10Z"
source: "WiFi"
message: "Scan terminé - 5 réseaux trouvés"
- timestamp: "2025-10-28T14:32:15Z"
source: "WiFi"
message: "Tentative de connexion à Hotel-Guest"
delete:
tags:
- Logs
summary: Clear system logs
description: Clears all stored log entries (keeps only the "logs cleared" entry)
operationId: clearLogs
responses:
'200':
description: Logs cleared successfully
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
/ws/logs:
get:
tags:
- Logs
summary: WebSocket for real-time logs
description: |
WebSocket endpoint for receiving real-time log updates.
Upon connection, all existing logs are sent, followed by new logs as they occur.
This is a WebSocket endpoint - upgrade the HTTP connection to WebSocket protocol.
operationId: logsWebSocket
responses:
'101':
description: WebSocket connection established
'400':
description: WebSocket upgrade failed
components:
schemas:
WiFiNetwork:
type: object
description: Discovered WiFi network information
properties:
ssid:
type: string
description: Network SSID (name)
example: "Hotel-Guest"
signal:
type: integer
description: Signal strength (1-5 scale)
minimum: 1
maximum: 5
example: 4
security:
type: string
description: Security type
enum:
- Open
- WEP
- WPA
- WPA2
example: "WPA2"
channel:
type: integer
description: WiFi channel number
minimum: 1
maximum: 165
example: 6
bssid:
type: string
description: Access point MAC address
pattern: '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'
example: "aa:bb:cc:dd:ee:ff"
required:
- ssid
- signal
- security
- channel
- bssid
WiFiConnectRequest:
type: object
description: Request to connect to a WiFi network
properties:
ssid:
type: string
description: Network SSID to connect to
example: "Hotel-Guest"
password:
type: string
description: Network password (empty string for open networks)
example: "guest1234"
required:
- ssid
- password
HotspotStatus:
type: object
description: Detailed hotspot status from hostapd_cli
properties:
state:
type: string
description: Hotspot state (ENABLED, DISABLED, etc.)
example: "ENABLED"
ssid:
type: string
description: Current SSID being broadcast
example: "TravelRouter"
bssid:
type: string
description: MAC address of the access point
pattern: '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'
example: "4a:e3:4e:09:57:f8"
channel:
type: integer
description: Current WiFi channel
minimum: 1
maximum: 14
example: 11
frequency:
type: integer
description: Frequency in MHz
example: 2462
numStations:
type: integer
description: Number of connected stations
minimum: 0
example: 2
hwMode:
type: string
description: Hardware mode (g, a, n, ac, etc.)
example: "g"
countryCode:
type: string
description: Country code
example: "VN"
required:
- state
ConnectedDevice:
type: object
description: Device connected to the hotspot
properties:
name:
type: string
description: Device hostname (may be empty when DHCP did not provide one)
example: "iPhone-12"
type:
type: string
description: Detected device type
enum:
- mobile
- tablet
- laptop
- desktop
- unknown
example: "mobile"
mac:
type: string
description: Device MAC address
pattern: '^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$'
example: "aa:bb:cc:11:22:33"
ip:
type: string
description: Assigned IP address
pattern: '^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$'
example: "192.168.1.100"
vendor:
type: string
description: Hardware vendor inferred from the MAC OUI prefix (empty when unknown)
example: "Apple"
signalDbm:
type: integer
format: int32
description: Wi-Fi signal strength in dBm (0 when unavailable, e.g. for non-hostapd backends)
example: -54
rxBytes:
type: integer
format: int64
description: Total bytes received from the device since connection (0 when unavailable)
example: 1048576
txBytes:
type: integer
format: int64
description: Total bytes sent to the device since connection (0 when unavailable)
example: 524288
connectedAt:
type: string
format: date-time
description: Timestamp when the station first appeared (best effort)
example: "2026-05-01T08:30:00Z"
required:
- name
- type
- mac
- ip
SystemStatus:
type: object
description: Overall system status
properties:
connected:
type: boolean
description: Whether router is connected to upstream WiFi
example: true
connectionState:
type: string
description: Current WiFi connection state
enum:
- connected
- disconnected
- connecting
- disconnecting
- roaming
example: "connected"
connectedSSID:
type: string
description: SSID of connected upstream network (empty if not connected)
example: "Hotel-Guest"
hotspotStatus:
allOf:
- $ref: '#/components/schemas/HotspotStatus'
nullable: true
description: Detailed hotspot status (null if hotspot is not running)
connectedCount:
type: integer
description: Number of devices connected to hotspot
minimum: 0
example: 3
dataUsage:
type: number
format: double
description: Total data usage in MB
example: 145.7
uptime:
type: integer
format: int64
description: System uptime in seconds
example: 3600
connectedDevices:
type: array
description: List of devices connected to hotspot
items:
$ref: '#/components/schemas/ConnectedDevice'
required:
- connected
- connectionState
- connectedSSID
- connectedCount
- dataUsage
- uptime
- connectedDevices
LogEntry:
type: object
description: System log entry
properties:
timestamp:
type: string
format: date-time
description: When the log entry was created
example: "2025-10-28T14:32:10Z"
source:
type: string
description: Log source component
enum:
- Système
- WiFi
- Hotspot
example: "WiFi"
message:
type: string
description: Log message
example: "Scan terminé - 5 réseaux trouvés"
required:
- timestamp
- source
- message
SuccessResponse:
type: object
description: Generic success response
properties:
status:
type: string
enum:
- success
example: "success"
required:
- status
Error:
type: object
description: Error response
properties:
error:
type: string
description: Error message
example: "Erreur lors du scan WiFi"
required:
- error