- Returns status, version, uptime, scanner_id - Component status: database, peer_sync, auto_scanner - Returns 200 for healthy, 503 for unhealthy - Tracks app start time for uptime calculation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
810 lines
12 KiB
Markdown
810 lines
12 KiB
Markdown
# RF Mapper API Reference
|
|
|
|
REST API documentation for RF Mapper web interface.
|
|
|
|
**Base URL:** `http://localhost:5000`
|
|
|
|
---
|
|
|
|
## System
|
|
|
|
### Health Check
|
|
|
|
Returns health status for monitoring and load balancers.
|
|
|
|
```
|
|
GET /api/health
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"status": "healthy",
|
|
"version": "1.0.0",
|
|
"uptime_seconds": 3600,
|
|
"uptime_human": "1h 0m",
|
|
"scanner_id": "rpios",
|
|
"components": {
|
|
"database": {
|
|
"status": "ok",
|
|
"device_count": 100
|
|
},
|
|
"peer_sync": {
|
|
"status": "ok",
|
|
"peer_count": 2
|
|
},
|
|
"auto_scanner": {
|
|
"status": "stopped"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Status Codes:**
|
|
- `200` - Healthy
|
|
- `503` - Unhealthy (component error)
|
|
|
|
**Component Status Values:**
|
|
- `ok` - Component working normally
|
|
- `disabled` - Component not enabled in config
|
|
- `error` - Component has errors
|
|
- `running` / `stopped` - For auto_scanner
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
# Simple health check
|
|
curl -s http://localhost:5000/api/health | jq '.status'
|
|
|
|
# Use in monitoring scripts
|
|
if curl -sf http://localhost:5000/api/health > /dev/null; then
|
|
echo "RF Mapper is healthy"
|
|
fi
|
|
```
|
|
|
|
---
|
|
|
|
## Scanning
|
|
|
|
### Trigger Scan
|
|
|
|
Performs WiFi and/or Bluetooth scan.
|
|
|
|
```
|
|
POST /api/scan
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `location` | string | `"web_scan"` | Location label for the scan |
|
|
| `lat` | number | config value | GPS latitude |
|
|
| `lon` | number | config value | GPS longitude |
|
|
| `scan_wifi` | boolean | `true` | Include WiFi networks |
|
|
| `scan_bluetooth` | boolean | `true` | Include Bluetooth devices |
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5000/api/scan \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"location": "kitchen", "scan_wifi": true, "scan_bluetooth": true}'
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"timestamp": "2026-02-01T14:30:00.123456",
|
|
"location": "kitchen",
|
|
"gps": {"lat": 50.8585, "lon": 4.3978},
|
|
"wifi_networks": [
|
|
{
|
|
"ssid": "HomeNetwork",
|
|
"bssid": "AA:BB:CC:DD:EE:FF",
|
|
"rssi": -45,
|
|
"channel": 6,
|
|
"frequency": 2437,
|
|
"encryption": "WPA2",
|
|
"manufacturer": "Cisco",
|
|
"estimated_distance_m": 3.5,
|
|
"signal_quality": "Excellent",
|
|
"floor": null,
|
|
"height_m": null
|
|
}
|
|
],
|
|
"bluetooth_devices": [
|
|
{
|
|
"address": "11:22:33:44:55:66",
|
|
"name": "iPhone",
|
|
"rssi": -60,
|
|
"device_class": "Phone",
|
|
"device_type": "Smartphone",
|
|
"manufacturer": "Apple",
|
|
"estimated_distance_m": 5.2,
|
|
"signal_quality": "Good",
|
|
"floor": null,
|
|
"height_m": null
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Quick Bluetooth Scan
|
|
|
|
Fast BLE-only scan for real-time tracking (uses bleak library).
|
|
|
|
```
|
|
POST /api/scan/bt
|
|
```
|
|
|
|
**Response:** Same as `/api/scan` but only `bluetooth_devices` populated.
|
|
|
|
---
|
|
|
|
### Get Latest Scan
|
|
|
|
Retrieve the most recent scan results.
|
|
|
|
```
|
|
GET /api/latest
|
|
```
|
|
|
|
**Response:** Same format as `/api/scan` response.
|
|
|
|
---
|
|
|
|
### List Scans
|
|
|
|
List saved scan files (most recent 50).
|
|
|
|
```
|
|
GET /api/scans
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
[
|
|
{
|
|
"filename": "scan_20260201_143000_kitchen.json",
|
|
"timestamp": "2026-02-01T14:30:00",
|
|
"location": "kitchen",
|
|
"wifi_count": 12,
|
|
"bt_count": 5
|
|
}
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
### Get Specific Scan
|
|
|
|
Retrieve a specific scan by filename.
|
|
|
|
```
|
|
GET /api/scans/<filename>
|
|
```
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl http://localhost:5000/api/scans/scan_20260201_143000_kitchen.json
|
|
```
|
|
|
|
---
|
|
|
|
## Position & Configuration
|
|
|
|
### GPS Position
|
|
|
|
Get or set current GPS position.
|
|
|
|
```
|
|
GET /api/position
|
|
POST /api/position
|
|
```
|
|
|
|
**POST Body:**
|
|
|
|
```json
|
|
{"lat": 50.8585, "lon": 4.3978}
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{"lat": 50.8585, "lon": 4.3978}
|
|
```
|
|
|
|
---
|
|
|
|
### Configuration
|
|
|
|
Get or update application configuration.
|
|
|
|
```
|
|
GET /api/config
|
|
POST /api/config
|
|
```
|
|
|
|
**POST Body:**
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `gps.latitude` | number | GPS latitude |
|
|
| `gps.longitude` | number | GPS longitude |
|
|
| `scanner.path_loss_exponent` | number | Distance calculation parameter |
|
|
| `save` | boolean | Persist changes to config file |
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5000/api/config \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"gps": {"latitude": 50.85, "longitude": 4.39}, "save": true}'
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"gps": {"latitude": 50.85, "longitude": 4.39},
|
|
"web": {"host": "0.0.0.0", "port": 5000},
|
|
"scanner": {
|
|
"wifi_interface": "wlan0",
|
|
"bt_scan_timeout": 10,
|
|
"path_loss_exponent": 2.5
|
|
},
|
|
"config_file": "/home/user/git/rf-mapper/config.yaml"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Building Configuration
|
|
|
|
Get or update building configuration for 3D visualization.
|
|
|
|
```
|
|
GET /api/building
|
|
POST /api/building
|
|
```
|
|
|
|
**POST Body:**
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `enabled` | boolean | Enable 3D building view |
|
|
| `name` | string | Building name |
|
|
| `floors` | integer | Number of floors |
|
|
| `floor_height_m` | number | Height per floor (meters) |
|
|
| `ground_floor_number` | integer | Ground floor number (0 or 1) |
|
|
| `current_floor` | integer | Scanner's current floor |
|
|
| `save` | boolean | Persist changes |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"enabled": true,
|
|
"name": "Home",
|
|
"floors": 3,
|
|
"floor_height_m": 3.0,
|
|
"ground_floor_number": 0,
|
|
"current_floor": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Device Management
|
|
|
|
### Set Device Floor
|
|
|
|
Assign a floor to a device (persists in database).
|
|
|
|
```
|
|
POST /api/device/<device_id>/floor
|
|
```
|
|
|
|
**Parameters:**
|
|
- `device_id`: BSSID (WiFi) or address (Bluetooth)
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"floor": 2, "height_m": 6.0}
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"status": "updated",
|
|
"device_id": "AA:BB:CC:DD:EE:FF",
|
|
"device_type": "wifi",
|
|
"floor": 2,
|
|
"height_m": 6.0
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Set Device Distance
|
|
|
|
Override estimated distance for a device.
|
|
|
|
```
|
|
POST /api/device/<device_id>/distance
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"distance": 5.5}
|
|
```
|
|
|
|
---
|
|
|
|
### Get All Floor Assignments
|
|
|
|
Retrieve all saved floor assignments.
|
|
|
|
```
|
|
GET /api/device/floors
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"AA:BB:CC:DD:EE:FF": 2,
|
|
"11:22:33:44:55:66": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Bluetooth Identification
|
|
|
|
### Identify Single Device
|
|
|
|
Get detailed info about a Bluetooth device.
|
|
|
|
```
|
|
GET /api/bluetooth/identify/<address>
|
|
```
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl http://localhost:5000/api/bluetooth/identify/11:22:33:44:55:66
|
|
```
|
|
|
|
---
|
|
|
|
### Batch Identify
|
|
|
|
Identify multiple devices (max 10).
|
|
|
|
```
|
|
POST /api/bluetooth/identify
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"addresses": ["11:22:33:44:55:66", "AA:BB:CC:DD:EE:FF"]}
|
|
```
|
|
|
|
---
|
|
|
|
## Auto-Scan
|
|
|
|
### Get Status
|
|
|
|
```
|
|
GET /api/autoscan
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"enabled": true,
|
|
"running": true,
|
|
"interval_minutes": 5,
|
|
"location_label": "auto_scan",
|
|
"scan_wifi": true,
|
|
"scan_bluetooth": true,
|
|
"last_scan_time": "2026-02-01T14:30:00",
|
|
"last_scan_result": {"timestamp": "...", "wifi_count": 12, "bt_count": 5},
|
|
"scan_count": 42
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Start Auto-Scan
|
|
|
|
```
|
|
POST /api/autoscan/start
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `interval_minutes` | integer | 5 | Scan interval |
|
|
| `location_label` | string | `"auto_scan"` | Location label |
|
|
| `scan_wifi` | boolean | `true` | Include WiFi |
|
|
| `scan_bluetooth` | boolean | `true` | Include Bluetooth |
|
|
| `save` | boolean | `false` | Persist to config |
|
|
|
|
---
|
|
|
|
### Stop Auto-Scan
|
|
|
|
```
|
|
POST /api/autoscan/stop
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"save": true}
|
|
```
|
|
|
|
---
|
|
|
|
### Update Settings
|
|
|
|
```
|
|
POST /api/autoscan/settings
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"interval_minutes": 10, "location_label": "living_room", "save": true}
|
|
```
|
|
|
|
---
|
|
|
|
## Historical Data API
|
|
|
|
All history endpoints require database to be enabled in config.
|
|
|
|
### List Devices
|
|
|
|
Get all tracked devices with statistics.
|
|
|
|
```
|
|
GET /api/history/devices
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `type` | string | Filter by `wifi` or `bluetooth` |
|
|
| `since` | string | ISO timestamp filter |
|
|
| `limit` | integer | Max results (default: 100) |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"devices": [
|
|
{
|
|
"device_id": "AA:BB:CC:DD:EE:FF",
|
|
"device_type": "wifi",
|
|
"name": "HomeNetwork",
|
|
"ssid": "HomeNetwork",
|
|
"manufacturer": "Cisco",
|
|
"first_seen": "2026-01-15T10:00:00",
|
|
"last_seen": "2026-02-01T14:30:00",
|
|
"total_observations": 500,
|
|
"custom_label": "Main Router",
|
|
"is_favorite": 1,
|
|
"assigned_floor": 1
|
|
}
|
|
],
|
|
"count": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Get Device Details
|
|
|
|
```
|
|
GET /api/history/devices/<device_id>
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"device": { ... },
|
|
"stats": {
|
|
"avg_rssi": -55.3,
|
|
"min_rssi": -75,
|
|
"max_rssi": -40,
|
|
"avg_distance_m": 4.2,
|
|
"min_distance_m": 1.5,
|
|
"max_distance_m": 12.0,
|
|
"total_observations": 500
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Get RSSI History
|
|
|
|
Time series RSSI data for a device.
|
|
|
|
```
|
|
GET /api/history/devices/<device_id>/rssi
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `since` | string | ISO timestamp filter |
|
|
| `limit` | integer | Max results (default: 1000) |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"device_id": "AA:BB:CC:DD:EE:FF",
|
|
"observations": [
|
|
{"timestamp": "2026-02-01T14:30:00", "rssi": -55, "distance_m": 4.2, "floor": 1}
|
|
],
|
|
"count": 100
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Get Activity Pattern
|
|
|
|
Hourly/daily activity pattern for a device.
|
|
|
|
```
|
|
GET /api/history/devices/<device_id>/activity
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
| Param | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `days` | integer | 7 | Analysis period |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"device_id": "AA:BB:CC:DD:EE:FF",
|
|
"period_days": 7,
|
|
"hourly_pattern": {
|
|
"8": {"count": 50, "avg_rssi": -55.0},
|
|
"9": {"count": 45, "avg_rssi": -52.3}
|
|
},
|
|
"daily_pattern": {
|
|
"0": 120,
|
|
"1": 115
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Set Device Label
|
|
|
|
```
|
|
POST /api/history/devices/<device_id>/label
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"label": "Living Room TV"}
|
|
```
|
|
|
|
---
|
|
|
|
### Toggle Favorite
|
|
|
|
```
|
|
POST /api/history/devices/<device_id>/favorite
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"favorite": true}
|
|
```
|
|
|
|
---
|
|
|
|
### Get Movement Events
|
|
|
|
```
|
|
GET /api/history/movement
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `device_id` | string | Filter by device |
|
|
| `since` | string | ISO timestamp filter |
|
|
| `limit` | integer | Max results (default: 100) |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"events": [
|
|
{
|
|
"id": 1,
|
|
"device_id": "11:22:33:44:55:66",
|
|
"timestamp": "2026-02-01T14:30:00",
|
|
"rssi_delta": 10,
|
|
"distance_delta_m": -2.5,
|
|
"direction": "approaching",
|
|
"velocity_m_s": 0.5
|
|
}
|
|
],
|
|
"count": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Get Alerts
|
|
|
|
```
|
|
GET /api/history/alerts
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
| Param | Type | Description |
|
|
|-------|------|-------------|
|
|
| `acknowledged` | boolean | Filter by acknowledged status |
|
|
| `type` | string | Filter by type: `new_device`, `device_absent`, `rssi_threshold` |
|
|
| `limit` | integer | Max results (default: 50) |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"alerts": [
|
|
{
|
|
"id": 1,
|
|
"alert_type": "new_device",
|
|
"device_id": "11:22:33:44:55:66",
|
|
"timestamp": "2026-02-01T14:30:00",
|
|
"message": "New Bluetooth device detected: iPhone (Apple)",
|
|
"acknowledged": 0
|
|
}
|
|
],
|
|
"count": 1
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Acknowledge Alert
|
|
|
|
```
|
|
POST /api/history/alerts/<alert_id>/acknowledge
|
|
```
|
|
|
|
---
|
|
|
|
### Get Activity Summary
|
|
|
|
```
|
|
GET /api/history/activity
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
| Param | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `hours` | integer | 24 | Period in hours |
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"period_hours": 24,
|
|
"since": "2026-01-31T14:30:00",
|
|
"active_wifi_devices": 12,
|
|
"active_bt_devices": 8,
|
|
"total_observations": 2500,
|
|
"movement_events": 15,
|
|
"new_devices": 2,
|
|
"scan_count": 288
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Get Database Stats
|
|
|
|
```
|
|
GET /api/history/stats
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"total_devices": 45,
|
|
"total_observations": 50000,
|
|
"total_scans": 1200,
|
|
"total_movement_events": 300,
|
|
"unread_alerts": 5,
|
|
"database_size_bytes": 5242880,
|
|
"database_size_mb": 5.0
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Manual Cleanup
|
|
|
|
Trigger data cleanup (removes old records).
|
|
|
|
```
|
|
POST /api/history/cleanup
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{"retention_days": 30}
|
|
```
|
|
|
|
**Response:**
|
|
|
|
```json
|
|
{
|
|
"retention_days": 30,
|
|
"cutoff": "2026-01-02T14:30:00",
|
|
"cleaned_at": "2026-02-01T14:30:00"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Error Responses
|
|
|
|
All endpoints return errors in this format:
|
|
|
|
```json
|
|
{"error": "Error message here"}
|
|
```
|
|
|
|
**Common HTTP Status Codes:**
|
|
|
|
| Code | Description |
|
|
|------|-------------|
|
|
| 200 | Success |
|
|
| 400 | Bad request (missing/invalid parameters) |
|
|
| 404 | Resource not found |
|
|
| 500 | Internal server error |
|
|
| 503 | Database not enabled |
|