f4823ace 2026-05-13 Pavel Safronov | 1 | # Haunt |
| 2 | |
| 3 | Android app that uses WiFi Round-Trip Time (RTT) ranging to fingerprint your phone's position and activate the corresponding Philips Hue light — no floor plans, no coordinate systems, no backend. |
| 4 | |
| 5 | ## How it works |
| 6 | |
| 7 | Three Google WiFi pucks each return a distance reading in meters. The combination of all three — a *distance-triple* — is unique to a physical location. During calibration you record a triple for each room. At runtime, the app finds the nearest stored triple and switches the light for that room. |
| 8 | |
| 9 | See [docs/wifi-rtt-hue-brief.md](docs/wifi-rtt-hue-brief.md) for the full design brief including accuracy expectations, gotchas, and development order. |
| 10 | |
| 11 | ## Hardware required |
| 12 | |
| 13 | - 3× Google WiFi pucks (2016 squat-cylinder model) — support IEEE 802.11mc FTM on 5 GHz |
| 14 | - Philips Hue Bridge v2 (square), on the same LAN |
| 15 | - Android phone: Pixel 2 or newer, Android 9+ |
| 16 | |
| 17 | ## Setup |
| 18 | |
| 19 | ### 1. Hue credentials |
| 20 | |
| 21 | Press the button on your Hue Bridge, then within 30 seconds: |
| 22 | |
| 23 | ```bash |
| 24 | curl -X POST http://<bridge-ip>/api \ |
| 25 | -H "Content-Type: application/json" \ |
| 26 | -d '{"devicetype":"haunt#android"}' |
| 27 | # Save the username from the response |
| 28 | |
| 29 | curl http://<bridge-ip>/api/<username>/lights |
| 30 | # Note the integer ID for each light you want to control |
| 31 | ``` |
| 32 | |
| 33 | ### 2. Find puck BSSIDs |
| 34 | |
| 35 | Run the app in debug mode — it lists every RTT-capable AP with its BSSID. Walk up to each puck; it will auto-pin to the map when you're within 0.5 m. Rename the pinned points (e.g. "Router kitchen") so you can identify which BSSID belongs to which puck. |
| 36 | |
| 37 | ### 3. Open in Android Studio |
| 38 | |
| 39 | Requires Android Studio Ladybug or later. On first open, let Gradle sync finish and generate the wrapper JAR, then run on a physical device (RTT does not work in the emulator). |
| 40 | |
35fda751 2026-05-13 Pavel Safronov | 41 | ## App icon |
| 42 | |
| 43 | The launcher icon is generated from `location.png` in the repo root. After replacing that file, regenerate all mipmap sizes and the adaptive-icon foreground with: |
| 44 | |
| 45 | ```bash |
| 46 | gradle :app:generateIcons |
| 47 | ``` |
| 48 | |
| 49 | To change the background color, edit the `bgColor` variable at the top of the `generateIcons` task in `app/build.gradle.kts`. The task is incremental — Gradle skips it if `location.png` hasn't changed. |
| 50 | |
4c8d760d 2026-05-16 Pavel Safronov | 51 | ### Attribution |
| 52 | |
| 53 | `location.png` is from the [Outline collection](https://www.flaticon.com/authors/icongeek26/outline?author_id=296&type=standard) by [icongeek26](https://www.flaticon.com/authors/icongeek26) on Flaticon. |
| 54 | |
35fda751 2026-05-13 Pavel Safronov | 55 | ## Orientation mode |
| 56 | |
| 57 | The map has a built-in compass mode. Tap **⊙ Orient** in the toolbar to enable it. The map then rotates to keep the phone's forward direction at the top, and a red **N** indicator appears at the edge showing where north is. |
| 58 | |
| 59 | **Calibration:** face your known north, hold the phone pointing that way, then drag the **N** circle to the top of the screen. The offset is saved and persists across restarts. |
| 60 | |
| 61 | ## Haunt mode |
| 62 | |
| 63 | Tap **Haunt** to enable haunt mode. While active, when you walk close to a registered Hue light (within ~1 m), that light blinks on and off slowly. When you move away or turn haunt mode off, the light returns to the state it was in before blinking started. |
| 64 | |
f4823ace 2026-05-13 Pavel Safronov | 65 | ## Development status |
| 66 | |
| 67 | | Layer | Status | Description | |
35fda751 2026-05-13 Pavel Safronov | 68 | | --- | --- | --- | |
f4823ace 2026-05-13 Pavel Safronov | 69 | | 1 | ✅ | Project scaffold, permissions, RTT availability check | |
35fda751 2026-05-13 Pavel Safronov | 70 | | 2 | ✅ | RTT ranging, debug map, add/rename/delete points, history trail | |
| 71 | | 3 | ✅ | Hue Bridge discovery, pairing, light/group listing and blinking | |
| 72 | | 4 | ✅ | Haunt mode — proximity detection, blink loop, state restoration | |
| 73 | | 5 | ✅ | Compass orientation mode — live map rotation, N indicator, calibration | |
| 74 | | 6 | ✅ | LAN device scanner — ARP + mDNS, pin network devices to map | |
| 75 | | 7 | — | ZoneMatcher — automatic light switching without haunt button | |
| 76 | | 8 | — | Background service — keep ranging alive when app is backgrounded | |
| 77 | | 9 | — | Tuning — average N readings, debounce K zone changes | |
f4823ace 2026-05-13 Pavel Safronov | 78 | |
| 79 | ## Package |
| 80 | |
| 81 | `net.fuzzyworld.haunt` |