Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/AngelAmoSanchez/TFG-RaspberryPi-BLE/llms.txt

Use this file to discover all available pages before exploring further.

The React web dashboard is a single-page application that gives you a live view of all Bluetooth detections captured by your Raspberry Pi nodes. Every panel updates automatically when new detections arrive over WebSocket, and a manual refresh button is always available if you want to pull fresh data on demand.

Top bar

The header row appears at the top of every page and contains four interactive controls.

Connection status

A ConnectionStatus indicator shows whether the WebSocket link to the backend is open. A green dot means the socket is connected; a red icon means the dashboard is running in polling-only mode.

Device selector

When more than one active Raspberry Pi is registered, a dropdown lets you filter all stats to a single device. If only one Pi is active, the selector is hidden automatically.

Time range picker

A TimeRangeSelector dropdown lets you switch between preset windows and a fully custom date-time range.

Manual refresh

The Actualizar button calls refresh() from useRealtimeStats to force an immediate API fetch regardless of the current mode.

Time range options

LabelValue passed to API
1 minutominutes=1
5 minutosminutes=5
30 minutosminutes=30
1 horaminutes=60
12 horasminutes=720
1 díaminutes=1440
7 díasminutes=10080
In preset mode the dashboard also auto-refreshes every 30 seconds via a setInterval in Dashboard.jsx.
Auto-refresh (every 30 s) is active only in preset mode. Switching to a custom date-time range pauses it so your historical view is not overwritten by live data.

Stats cards

Three summary cards sit below the top bar in a responsive three-column grid.

Dispositivos Detectados

Shows stats.total.unique_devices — the count of distinct Bluetooth MAC hashes seen within the selected window. The subtitle displays the total raw detection count (total_detections).

Personas Estimadas

Shows stats.total.estimated_people, calculated by the backend using a 1.5 devices-per-person ratio (unique_devices / 1.5, rounded).

Umbrales RSSI

An inline ThresholdSettings widget — not a read-only number but a live configuration panel (see Threshold settings below).

Zone distribution chart

The ZoneChart component renders a Recharts PieChart that shows the share of estimated people per RSSI zone.
// ZoneChart.jsx — how zones map to colours
const COLORS = {
  'Near':   '#FF474C',
  'Medium': '#FFA800',
  'Far':    '#009CDD'
};
Each slice is labelled with its zone name and percentage. The tooltip shows both the estimated people count and the number of unique devices for that slice:
<Tooltip
  formatter={(value, name, props) => [
    `${value} personas (${props.payload.devices} dispositivos)`,
    props.payload.name
  ]}
/>
Alongside the pie chart, a zone detail table lists every zone with:
  • Unique device count
  • Estimated people count (large blue number)
  • Average RSSI in dBm (data.avg_rssi.toFixed(1))
If no detections exist for the selected window, the chart area displays “No hay datos disponibles” rather than rendering an empty chart.

IoT devices list

The DeviceList component renders a full table of all registered Raspberry Pi nodes. Each row shows:
ColumnSource field
Statusdevice.is_active — green check or red X icon
ID / Namedevice.name (primary) + device.device_id (secondary)
Locationdevice.location
Last seendevice.last_seen formatted with Intl.DateTimeFormat (Europe/Madrid)
A toggle button above the table switches between showing all devices and showing only active ones:
// Dashboard.jsx
<button onClick={() => setShowInactive(!showInactive)}>
  {showInactive ? <><EyeOff /> Ocultar inactivos</> : <><Eye /> Mostrar todos</>}
</button>
The device list itself auto-refreshes every 30 seconds via the useDevices hook, independently of the stats refresh cycle.

Export filters panel

The ExportFilters component lets you download detection data as a CSV file. It sits in the right column beside the device list.

Filter modes

Preset

Choose from six preset time windows: last 30 minutes, 1 hour, 6 hours, 24 hours, 7 days, or 30 days. The corresponding query parameter (last_minutes, last_hours, or last_days) is appended to the export URL automatically.
Enter an integer and pick a unit (minutes, hours, or days). The component strips non-numeric characters and leading zeros from the input before building the last_<unit>=<value> parameter.
Pick a start date and an end date. The component validates that start precedes end before enabling the download button. Parameters sent: start_date and end_date.

Additional filters

Two optional dropdowns narrow the export further:
  • Zonenear, medium, or far (maps to the zone query parameter)
  • IoT device — any registered device, including inactive ones (maps to the device_id parameter)

CSV download

The export calls GET /api/v1/export/detections/csv with the constructed query string. The filename is read from the Content-Disposition response header; it falls back to detections.csv if the header is absent. The downloaded CSV includes: ID, device hash, RSSI, zone, timestamp, device ID, date, and time.
In date-range mode, both start and end dates are required. The download button stays disabled until both fields are filled and the range is valid.

Threshold settings

The ThresholdSettings widget occupies the third stats card slot and lets you tune the RSSI boundaries used to classify detections into Near, Medium, and Far zones.
FieldDefaultConstraint
NEAR threshold-60 dBmMust be greater than MEDIUM
MEDIUM threshold-75 dBmMust be less than NEAR
Both fields accept negative integers between -1 and -127. Changes are saved automatically on blur (onBlur) by calling PUT /api/v1/settings/thresholds. A Reset button restores both values to their defaults by calling POST /api/v1/settings/thresholds/reset.
// ThresholdSettings.jsx — auto-save on blur
const handleBlur = async (field) => {
  // ...validation...
  await api.updateThresholds(parseInt(near), parseInt(medium));
};

Real-time WebSocket connection

The useRealtimeStats hook manages the WebSocket lifecycle. It connects to VITE_WS_URL (falling back to ws://localhost:8000) and listens for three event types:
EventAction
connection_statusUpdates the wsConnected flag shown in the top bar
stats_updateReplaces stats in state (preset mode only)
detection_eventTriggers a fresh fetchStats() call (preset mode only)
The socket sends a ping message every 15 seconds to keep the connection alive, and reconnects automatically with exponential backoff (up to 5 attempts, starting at 1 second) on unexpected disconnection.
// websocket.js — reconnection backoff
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
this.reconnectTimer = setTimeout(() => this.connect(), delay);

Build docs developers (and LLMs) love