5.5 KiB
Presence Daemon — Person Presence Intelligence
Passive multi-signal WiFi/ARP/DHCP/BLE person presence tracking daemon for BigBrother drop implant.
Quick Start
cd /home/n0mad1k/tools/bigbrother/presence
sudo bash install.sh
This creates /opt/sensor/sensor.py, initializes the database, and starts the systemd service.
Configuration
Environment variables:
PRESENCE_MONITOR_IFACE— WiFi monitor mode interface (default: wlan1)PRESENCE_DATA_IFACE— Connected network interface for ARP/DHCP (default: wlan0)PRESENCE_DB_PATH— SQLite database location (default: /opt/presence/presence.db)PRESENCE_MATRIX_WEBHOOK— Matrix webhook URL for alerts (default: empty, no alerts)
Example systemd override:
sudo systemctl edit sensor
# Add to [Service] section:
# Environment=PRESENCE_MONITOR_IFACE=wlan2
# Environment=PRESENCE_MATRIX_WEBHOOK=https://matrix.example.com/hook/...
Architecture
Sensor Threads (4 concurrent)
-
Probe Sniffer — WiFi probe request capture on monitor interface
- Passive 802.11 frame parsing (type 0, subtype 4)
- Extracts source MAC → +0.60 certainty bump
- Runs on PRESENCE_MONITOR_IFACE
-
ARP Listener — netlink RTM_NEWNEIGH/RTM_DELNEIGH events
- Kernel neighbor discovery events
- Filters infrastructure IPs
- Extracts MAC → +0.50 certainty bump
-
DHCP Sniffer — AF_PACKET raw socket on data interface
- Captures DHCP DISCOVER/REQUEST packets
- Extracts client MAC (chaddr field)
- Extracts hostname (option 12)
- MAC → +0.80 certainty bump
-
BLE Scanner — Passive BLE device discovery
- Uses
bleaklibrary if available - Gracefully disables if ImportError
- Device address → +0.40 certainty bump
- Uses
Core Logic
Signal Fusion (per person):
- Collect all device certainties
- Apply exponential decay:
certainty × e^(-0.08 × age_minutes) - Aggregate:
max + 0.08 × second_max - Check state machine
Presence Anchor (critical):
- Once PRESENT (certainty ≥ 0.40), hold PRESENT for 45 minutes from last signal
- Prevents false ABSENT from temporary signal loss (iOS suppression, WiFi roam, power save)
- After 45 minutes without signal ≥ 0.40 → ABSENT
State Machine:
UNKNOWN → PRESENT → ABSENT → PRESENT
↓ agg_cert ↓
└─────────≥ 0.40 45 min no signal
Alerting:
- UNKNOWN → PRESENT: "ARRIVED" alert
- PRESENT → ABSENT: "DEPARTED" alert
- Via Matrix webhook if configured
Database Schema
persons — Named people
- id (PK)
- name — Person name
- notes — Optional metadata
devices — MAC-to-person mapping
- mac (PK)
- person_id (FK)
- label — Device name (iPhone, Laptop, etc.)
- added_at — Timestamp
signals — Raw signal observations
- id (PK)
- mac — Device MAC
- signal_type — "probe", "arp", "dhcp", or "ble"
- certainty — Aggregated certainty after this signal
- ts — Observation timestamp
occupancy_log — State transitions
- id (PK)
- person_id (FK)
- old_status — Previous state
- new_status — New state
- ts — Transition timestamp
HTTP Status Endpoint
Returns JSON:
{
"persons": [
{
"id": 1,
"name": "Alice",
"status": "PRESENT",
"last_change": 1712761234.5
}
]
}
Limitations (Phase 1)
- No auto-enrollment: Device-to-person mapping must be set up manually in database
- No mDNS parsing: Hostnames are not extracted or used for identity
- BLE optional: Requires
bleaklibrary; gracefully disabled if missing - Monitor mode required: Probe sniffer needs separate WiFi adapter in monitor mode
- Root access needed: Raw sockets require CAP_NET_ADMIN or root
- Single location: No multi-room support
Files
presence_daemon.py— Main daemon (1000+ lines)presence_schema.sql— SQLite schemainstall.sh— Deployment scriptAUDIT_impl.md— Implementation notes and audit checklistREADME.md— This file
Logging
Logs to /var/log/sensor.log and stdout. Log level: INFO (debug messages only on errors).
Example log output:
2026-04-10 14:54:32,123 [INFO] Database initialized at /opt/sensor/sensor.db
2026-04-10 14:54:32,124 [INFO] Loaded 2 persons from database
2026-04-10 14:54:32,125 [INFO] Probe sniffer started on wlan1
2026-04-10 14:54:32,126 [INFO] ARP listener started
2026-04-10 14:54:32,127 [INFO] DHCP sniffer started on wlan0
2026-04-10 14:54:32,128 [INFO] BLE scanner started
2026-04-10 14:54:32,129 [INFO] Status server started on http://127.0.0.1:9191
2026-04-10 14:54:32,130 [INFO] Sensor daemon started
Testing
-
Verify systemd service is running:
sudo systemctl status sensor -
Check database initialization:
sqlite3 /opt/sensor/sensor.db ".tables" -
Query persons:
sqlite3 /opt/sensor/sensor.db "SELECT * FROM persons;" -
Query recent signals:
sqlite3 /opt/sensor/sensor.db "SELECT * FROM signals ORDER BY ts DESC LIMIT 10;" -
Check status endpoint:
curl http://127.0.0.1:9191/ -
Check logs:
tail -f /var/log/sensor.log
Phase 2 Roadmap
- Auto-enrollment from mDNS hostnames
- BLE MAC signature recognition (Apple Watch, AirPods)
- Device quorum (multi-device presence confirmation)
- Tentative device linking via co-occurrence windows
Phase 3 Roadmap
- Pattern of life analytics
- Arrival/departure time learning
- Occupancy forecasting
- Multi-location aggregation