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.

This page covers the problems most commonly encountered when deploying and operating the BLE People Counter. Each section describes the symptom, the likely cause, and the steps to resolve it.
Symptom: The agent logs No devices detected in this scan on every cycle.Likely causes:
  • The Bluetooth adapter is off or not recognized by the OS.
  • The cap_net_raw and cap_net_admin capabilities were not applied to the Python binary.
  • The bluetooth system service is not running.
Resolution:
1

Check the Bluetooth service

sudo systemctl status bluetooth
If it is inactive, start it:
sudo systemctl enable bluetooth
sudo systemctl start bluetooth
2

Verify the adapter is up

hciconfig hci0
The output should contain UP RUNNING. If the adapter is missing or DOWN, try:
sudo hciconfig hci0 up
3

Re-apply BLE capabilities

The install.sh script sets the required capabilities on the virtual-environment Python binary. If the venv was recreated or updated, run this command again:
sudo setcap cap_net_raw,cap_net_admin+eip /home/pi/TFG-RaspberryPi-BLE/raspberry-pi/venv/bin/python3
4

Test with the calibration script

Run calibrate_ble.py manually to confirm that Bleak can scan at all:
source venv/bin/activate
python3 calibrate_ble.py
If this works but the agent does not, compare the Python binary path used by systemd with the one that has setcap applied.
Symptom: The agent exits immediately with:
ModuleNotFoundError: No module named 'bleak'
Cause: The script is being run with the system Python instead of the virtual environment Python, or the virtual environment was not set up correctly.Resolution:
1

Activate the virtual environment

source /home/pi/TFG-RaspberryPi-BLE/raspberry-pi/venv/bin/activate
python3 -c "import bleak; print(bleak.__version__)"
2

Reinstall dependencies if needed

pip install -r requirements.txt
3

Verify the systemd ExecStart path

The service unit should point to the venv Python directly, not to python3:
ExecStart=/home/pi/TFG-RaspberryPi-BLE/raspberry-pi/venv/bin/python3 src/main.py
Inspect the installed unit:
cat /etc/systemd/system/ble-scanner.service
Symptom: The agent logs Sin broker MQTT configurado, se usará MockMQTTClient (simulado) or connection refused errors.Cause: The MQTT_BROKER variable is not set, is set to the default placeholder broker.emqx.io, or the broker is unreachable from the Pi’s network.The agent checks for this condition explicitly:
if not self.config.mqtt.broker or self.config.mqtt.broker == "broker.emqx.io":
    logger.warning("Sin broker MQTT configurado, se usará MockMQTTClient (simulado)")
    return MockMQTTClient(device_id=self.config.device_id)
Resolution:
  • Set MQTT_BROKER in .env to your broker’s hostname or IP address.
  • Set MQTT_USERNAME and MQTT_PASSWORD if your broker requires authentication.
  • Confirm the Pi can reach the broker:
    ping your-mqtt-broker-host
    
  • Check that port 1883 (or your configured MQTT_PORT) is open:
    nc -zv your-mqtt-broker-host 1883
    
Symptom: The agent logs No se pudo conectar al backend, entrando en modo offline or HTTP connection errors in the log file.Cause: HTTP_BASE_URL is wrong, the backend is not running, or a firewall is blocking the connection.Resolution:
1

Verify the URL in .env

grep HTTP_BASE_URL .env
The value must be the full URL including scheme, for example https://your-backend.fly.dev. No trailing slash.
2

Test connectivity from the Pi

curl -v https://your-backend.fly.dev/health
A 200 response confirms the backend is reachable.
3

Check the API key

If the backend requires an API key, set HTTP_API_KEY in .env to the same value as API_KEY on the backend. A 401 response from the health check suggests a key mismatch.
4

Check firewall rules

Ensure the Pi’s network allows outbound HTTPS (port 443) or HTTP (port 8000) to the backend host.
Symptom: docker compose up exits immediately or the backend container restarts in a loop.Cause: Most often the database is not ready yet, or DATABASE_URL is misconfigured.Resolution:
1

Check the container logs

docker compose logs backend
Look for sqlalchemy or asyncpg connection errors.
2

Verify the database is healthy

The docker-compose.yml uses a healthcheck so the backend waits for Postgres:
depends_on:
  postgres:
    condition: service_healthy
Check the Postgres container:
docker compose logs postgres
docker compose ps
If Postgres is unhealthy, check disk space and the POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB environment variables.
3

Verify DATABASE_URL

The URL format for the async driver is:
postgresql+asyncpg://user:password@host:5432/database
For the Docker Compose setup, the host must be postgres (the service name), not localhost.
Symptom: The backend starts but immediately fails with errors mentioning alembic, revision, or missing database columns.Cause: The database schema is out of date or migrations have not been applied.Resolution:
1

Run migrations manually

Execute the migration command inside the running backend container:
docker compose exec backend alembic upgrade head
2

Check for conflicts

If Alembic reports a revision conflict or a missing migration file:
docker compose exec backend alembic history
docker compose exec backend alembic current
Compare the current revision with the latest in alembic/versions/.
3

Reset the database (development only)

docker compose down -v   # removes the postgres_data volume
docker compose up -d
docker compose exec backend alembic upgrade head
This deletes all stored detection data. Only do this in development.
Symptom: The dashboard loads but every data panel shows an error message.Cause: The frontend cannot reach the backend API. The three most common reasons are:
  1. VITE_API_URL is not set or points to the wrong URL.
  2. The backend is returning CORS errors because the frontend’s origin is not in the allowed list.
  3. The backend is down.
Resolution:
1

Check the API URL environment variable

In Vercel, confirm that VITE_API_URL is set to the full backend URL (e.g., https://your-backend.fly.dev). After changing environment variables in Vercel, redeploy.
2

Inspect the browser console

Open browser DevTools → Console. A CORS error looks like:
Access to fetch at 'https://your-backend.fly.dev/api/v1/...' from origin
'https://your-app.vercel.app' has been blocked by CORS policy
If you see this, add your Vercel domain to cors_origins in backend-cloud/src/config.py and redeploy the backend.
3

Confirm the backend is running

curl https://your-backend.fly.dev/health
Symptom: Real-time updates on the dashboard do not work. The browser console shows a WebSocket connection failure.Cause: Protocol mismatch (ws:// instead of wss:// for HTTPS frontends), CORS restrictions on the WebSocket upgrade, or the backend port is not reachable.Resolution:
  • Frontends served over HTTPS must use wss:// for WebSocket connections. A ws:// URL will be blocked by the browser.
  • Confirm WEBSOCKET_ENABLED is true on the backend (it is the default).
  • The Fly.io configuration forces HTTPS and forwards WebSocket upgrades automatically. If using Docker Compose behind a reverse proxy (nginx, Caddy), ensure the proxy passes the Upgrade and Connection headers.
  • Check the browser Network tab → WS tab for the exact error code and message.
Symptom: The dashboard shows a people count that is significantly higher or lower than the actual number of people present.Cause: RSSI thresholds are not calibrated for the environment, the DEVICES_PER_PERSON ratio does not match actual device density, or MAC randomization is inflating counts.Resolution:
1

Run the calibration script

Run calibrate_ble.py in the actual deployment space with a known number of people:
python3 calibrate_ble.py
Compare the suggested thresholds with the current values.
2

Update thresholds via the API

curl -X PUT https://your-backend/api/v1/settings/thresholds \
  -H "Content-Type: application/json" \
  -d '{"near_threshold": -58, "medium_threshold": -74}'
This triggers retroactive reclassification of all historical detections.
3

Adjust DEVICES_PER_PERSON

Do a controlled test: count N people manually and record the raw device count. Set:
DEVICES_PER_PERSON = raw_device_count / N
Update the environment variable on the backend and restart.
See the zone tuning guide for full details.
Symptom: systemctl status ble-scanner shows the service repeatedly entering activating and failed states. The restart counter climbs.Cause: A fatal error at startup — most commonly a configuration error in .env, a missing Python dependency, or a permissions problem.Resolution:
1

Follow the service logs

sudo journalctl -u ble-scanner -f
Look for the error message just before each restart. Python tracebacks are printed in full.
2

Check .env for required variables

The agent exits with sys.exit(1) if DEVICE_ID is missing or COMMUNICATION_MODE is invalid:
grep -E "DEVICE_ID|COMMUNICATION_MODE" .env
3

Run the agent manually to reproduce the error

source venv/bin/activate
python3 src/main.py
Running interactively gives you the full error output without systemd truncation.
4

Check the restart limit

The unit allows 10 restarts within 200 seconds before systemd stops trying:
StartLimitBurst=10
StartLimitInterval=200
If the limit is reached, reset the counter:
sudo systemctl reset-failed ble-scanner
sudo systemctl start ble-scanner

Build docs developers (and LLMs) love