Add presence daemon user documentation and architecture guide
This commit is contained in:
@@ -0,0 +1,202 @@
|
||||
# Presence Daemon — Person Presence Intelligence
|
||||
|
||||
Passive multi-signal WiFi/ARP/DHCP/BLE person presence tracking daemon for BigBrother drop implant.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
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:
|
||||
```bash
|
||||
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)
|
||||
|
||||
1. **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
|
||||
|
||||
2. **ARP Listener** — netlink RTM_NEWNEIGH/RTM_DELNEIGH events
|
||||
- Kernel neighbor discovery events
|
||||
- Filters infrastructure IPs
|
||||
- Extracts MAC → +0.50 certainty bump
|
||||
|
||||
3. **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
|
||||
|
||||
4. **BLE Scanner** — Passive BLE device discovery
|
||||
- Uses `bleak` library if available
|
||||
- Gracefully disables if ImportError
|
||||
- Device address → +0.40 certainty bump
|
||||
|
||||
### 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
|
||||
|
||||
GET http://127.0.0.1:9191/
|
||||
|
||||
Returns JSON:
|
||||
```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 `bleak` library; 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 schema
|
||||
- `install.sh` — Deployment script
|
||||
- `AUDIT_impl.md` — Implementation notes and audit checklist
|
||||
- `README.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
|
||||
|
||||
1. Verify systemd service is running:
|
||||
```bash
|
||||
sudo systemctl status sensor
|
||||
```
|
||||
|
||||
2. Check database initialization:
|
||||
```bash
|
||||
sqlite3 /opt/sensor/sensor.db ".tables"
|
||||
```
|
||||
|
||||
3. Query persons:
|
||||
```bash
|
||||
sqlite3 /opt/sensor/sensor.db "SELECT * FROM persons;"
|
||||
```
|
||||
|
||||
4. Query recent signals:
|
||||
```bash
|
||||
sqlite3 /opt/sensor/sensor.db "SELECT * FROM signals ORDER BY ts DESC LIMIT 10;"
|
||||
```
|
||||
|
||||
5. Check status endpoint:
|
||||
```bash
|
||||
curl http://127.0.0.1:9191/
|
||||
```
|
||||
|
||||
6. Check logs:
|
||||
```bash
|
||||
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
|
||||
Reference in New Issue
Block a user