|
| 1 | +# MeshCore GOME WarDriver - AI Agent Instructions |
| 2 | + |
| 3 | +> **Keeping This File Updated**: When you make architectural changes, add new workflows, or modify critical patterns, update this file. Ask the AI: *"Update .github/copilot-instructions.md to reflect the changes I just made"* - it will analyze the modifications and update relevant sections. |
| 4 | +
|
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Browser-based Progressive Web App for wardriving with MeshCore mesh network devices. Connects via Web Bluetooth to send GPS-tagged pings to a `#wardriving` channel, track repeater echoes, and post coverage data to the MeshMapper API for community mesh mapping. |
| 8 | + |
| 9 | +**Tech Stack**: Vanilla JavaScript (ES6 modules), Web Bluetooth API, Geolocation API, Tailwind CSS v4 |
| 10 | + |
| 11 | +**Critical Files**: |
| 12 | +- `content/wardrive.js` (4500+ lines) - Main application logic |
| 13 | +- `content/mc/` - MeshCore BLE protocol library (Connection classes, Packet parsing, Buffer utilities) |
| 14 | +- `index.html` - Single-page UI with embedded Leaflet map |
| 15 | +- `docs/` - Comprehensive workflow documentation (CONNECTION_WORKFLOW.md, PING_WORKFLOW.md, etc.) |
| 16 | + |
| 17 | +## Architecture & Data Flow |
| 18 | + |
| 19 | +### 1. Connection Architecture |
| 20 | +Three-layer connection system: |
| 21 | +- **BLE Layer**: `WebBleConnection` (extends `Connection` base class) handles GATT connection, characteristic notifications |
| 22 | +- **Protocol Layer**: `Connection.js` (2200+ lines) implements MeshCore companion protocol - packet framing, encryption, channel management, device queries |
| 23 | +- **App Layer**: `wardrive.js` orchestrates connect/disconnect workflows with 10-step sequences (see `docs/CONNECTION_WORKFLOW.md`) |
| 24 | + |
| 25 | +**Connect Sequence**: BLE GATT → Protocol Handshake → Device Info → Time Sync → Capacity Check (API slot acquisition) → Channel Setup → GPS Init → Connected |
| 26 | + |
| 27 | +### 2. Ping Lifecycle & API Queue System |
| 28 | +Two independent data flows merge into a unified API batch queue: |
| 29 | + |
| 30 | +**TX Flow** (Transmit): |
| 31 | +1. User sends ping → `sendPing()` validates GPS/geofence/distance |
| 32 | +2. Sends `@[MapperBot]<LAT LON>[ <power>]` to `#wardriving` channel via BLE |
| 33 | +3. Starts 6-second RX listening window for repeater echoes |
| 34 | +4. After window: posts to API queue with type "TX" |
| 35 | +5. Triggers 3-second flush timer for real-time map updates |
| 36 | + |
| 37 | +**RX Flow** (Receive - Passive monitoring): |
| 38 | +1. Always-on `handleUnifiedRxLogEvent()` captures ALL incoming packets (no filtering) |
| 39 | +2. Validates path length > 0 (must route via repeater, not direct) |
| 40 | +3. Buffers RX events per repeater with GPS coordinates |
| 41 | +4. Flushes to API queue on 25m movement or 30s timeout, type "RX" |
| 42 | + |
| 43 | +**API Queue** (`apiQueue.messages[]`): |
| 44 | +- Max 50 messages, auto-flush on size/30s timer/TX triggers |
| 45 | +- Batch POST to `yow.meshmapper.net/wardriving-api.php` |
| 46 | +- See `docs/FLOW_WARDRIVE_API_QUEUE_DIAGRAM.md` for visual flow |
| 47 | + |
| 48 | +### 3. GPS & Geofencing |
| 49 | +- **GPS Watch**: Continuous `navigator.geolocation.watchPosition()` with high accuracy |
| 50 | +- **Freshness**: Manual pings use 60s max age, auto pings require fresh acquisition |
| 51 | +- **Ottawa Geofence**: 150km radius from Parliament Hill (45.4215, -75.6972) - hard boundary |
| 52 | +- **Min Distance Filter**: 25m between pings (prevents spam, separate from 25m RX batch trigger) |
| 53 | + |
| 54 | +### 4. State Management |
| 55 | +Global `state` object tracks: |
| 56 | +- `connection`: Active BLE connection instance |
| 57 | +- `wardrivingChannel`: Channel object for ping sends |
| 58 | +- `txRxAutoRunning` / `autoTimerId` / `nextAutoPingTime`: Auto-ping state |
| 59 | +- `lastPingLat/Lon`: For distance validation |
| 60 | +- `cooldownEndTime`: 7-second cooldown after each ping |
| 61 | +- `sessionId`: UUID for correlating TX/RX events per wardrive session |
| 62 | + |
| 63 | +**RX Batch Buffer**: `Map` keyed by repeater node ID → `{rxEvents: [], bufferedSince, lastFlushed, flushTimerId}` |
| 64 | + |
| 65 | +## Critical Developer Workflows |
| 66 | + |
| 67 | +### Build & Development |
| 68 | +```bash |
| 69 | +npm install # Install Tailwind CLI |
| 70 | +npm run build:css # One-time CSS build |
| 71 | +npm run watch:css # Watch mode for development |
| 72 | +``` |
| 73 | + |
| 74 | +**No bundler/compiler** - Open `index.html` directly in browser (Chrome/Chromium required for Web Bluetooth). |
| 75 | + |
| 76 | +### Debug Logging System |
| 77 | +All debug output controlled by `DEBUG_ENABLED` flag (URL param `?debug=true` or hardcoded): |
| 78 | +```javascript |
| 79 | +debugLog("[TAG] message", ...args); // General info |
| 80 | +debugWarn("[TAG] message", ...args); // Warnings |
| 81 | +debugError("[TAG] message", ...args); // Errors (also adds to UI Error Log) |
| 82 | +``` |
| 83 | + |
| 84 | +**Required Tags** (see `docs/DEVELOPMENT_REQUIREMENTS.md`): `[BLE]`, `[GPS]`, `[PING]`, `[API QUEUE]`, `[RX BATCH]`, `[UNIFIED RX]`, `[UI]`, etc. NEVER log without a tag. |
| 85 | + |
| 86 | +### Status Message System |
| 87 | +**Two separate status bars** (NEVER mix them): |
| 88 | +1. **Connection Status** (`setConnStatus(text, color)`) - ONLY "Connected", "Connecting", "Disconnected", "Disconnecting" |
| 89 | +2. **Dynamic Status** (`setDynamicStatus(text, color, immediate)`) - All operational messages, 500ms minimum visibility, blocks connection words |
| 90 | + |
| 91 | +Use `STATUS_COLORS` constants: `idle`, `success`, `warning`, `error`, `info` |
| 92 | + |
| 93 | +## Project-Specific Patterns |
| 94 | + |
| 95 | +### 1. Countdown Timer Pattern |
| 96 | +Reusable countdown system for cooldowns, auto-ping intervals, RX listening windows: |
| 97 | +```javascript |
| 98 | +function createCountdownTimer(getEndTime, getStatusMessage) { |
| 99 | + // Returns timer state, updates UI every 500ms |
| 100 | + // Handles pause/resume for manual ping interrupts |
| 101 | +} |
| 102 | +``` |
| 103 | +Used by `startAutoCountdown()`, `startRxListeningCountdown()`, cooldown logic. |
| 104 | + |
| 105 | +### 2. Channel Hash & Decryption |
| 106 | +**Pre-computed at startup**: |
| 107 | +```javascript |
| 108 | +WARDRIVING_CHANNEL_KEY = await deriveChannelKey("#wardriving"); // PBKDF2 SHA-256 |
| 109 | +WARDRIVING_CHANNEL_HASH = await computeChannelHash(key); // PSK channel identifier |
| 110 | +``` |
| 111 | +Used for: |
| 112 | +- Repeater echo detection (match `channelHash` in received packets) |
| 113 | +- Message decryption (AES-ECB via aes-js library) |
| 114 | + |
| 115 | +### 3. Wake Lock Management |
| 116 | +Auto-ping mode acquires Screen Wake Lock to keep GPS active: |
| 117 | +```javascript |
| 118 | +await acquireWakeLock(); // On auto-ping start |
| 119 | +await releaseWakeLock(); // On stop/disconnect |
| 120 | +``` |
| 121 | +Handles visibility changes (release on hidden, reacquire on visible). |
| 122 | + |
| 123 | +### 4. Capacity Check (API Slot Management) |
| 124 | +Before connecting, app must acquire a slot from MeshMapper backend: |
| 125 | +```javascript |
| 126 | +POST /capacitycheck.php { iatacode: "YOW", apikey: "...", apiver: "1.6.0" } |
| 127 | +Response: { valid: true, reason: null } or { valid: false, reason: "outofdate" } |
| 128 | +``` |
| 129 | +Slot released on disconnect. Prevents backend overload. |
| 130 | + |
| 131 | +## Documentation Requirements (CRITICAL) |
| 132 | + |
| 133 | +**ALWAYS update docs when modifying workflows**: |
| 134 | + |
| 135 | +1. **Connection Changes** → Update `docs/CONNECTION_WORKFLOW.md` (steps, states, error handling) |
| 136 | +2. **Ping/Auto-Ping Changes** → Update `docs/PING_WORKFLOW.md` (validation, lifecycle, UI impacts) |
| 137 | +3. **New Status Messages** → Add to `docs/STATUS_MESSAGES.md` (exact text, trigger, color) |
| 138 | +4. **Code Comments** → Use JSDoc (`@param`, `@returns`) for all functions |
| 139 | +5. **Architecture/Pattern Changes** → Update `.github/copilot-instructions.md` (this file) to reflect new patterns, data flows, or critical gotchas |
| 140 | + |
| 141 | +### Status Message Documentation Format |
| 142 | +```markdown |
| 143 | +#### Message Name |
| 144 | +- **Message**: `"Exact text shown"` |
| 145 | +- **Color**: Green/Red/Yellow/Blue (success/error/warning/info) |
| 146 | +- **When**: Detailed trigger condition |
| 147 | +- **Source**: `content/wardrive.js:functionName()` |
| 148 | +``` |
| 149 | + |
| 150 | +## Integration Points & External APIs |
| 151 | + |
| 152 | +### MeshMapper API (yow.meshmapper.net) |
| 153 | +- **Capacity Check**: `capacitycheck.php` - Slot acquisition before connect |
| 154 | +- **Wardrive Data**: `wardriving-api.php` - Batch POST TX/RX coverage blocks |
| 155 | + - Payload: `[{type:"TX"|"RX", lat, lon, who, power, heard, session_id, iatacode}]` |
| 156 | + - Auth: `apikey` in JSON body (NOT query string - see `docs/GEO_AUTH_DESIGN.md`) |
| 157 | + |
| 158 | +### MeshCore Protocol (content/mc/) |
| 159 | +Key methods on `Connection` class: |
| 160 | +- `deviceQuery(protoVer)` - Protocol handshake |
| 161 | +- `getDeviceName()`, `getPublicKey()`, `getDeviceSettings()` - Device info |
| 162 | +- `sendTime()` - Time sync |
| 163 | +- `getChannels()`, `createChannel()`, `deleteChannel()` - Channel CRUD |
| 164 | +- `sendChannelMsg(channel, text)` - Send text message to channel |
| 165 | + |
| 166 | +**Packet Structure**: Custom binary protocol with BufferReader/Writer utilities for serialization. |
| 167 | + |
| 168 | +## Common Pitfalls & Gotchas |
| 169 | + |
| 170 | +1. **Unified RX Handler accepts ALL packets** - No header filtering at entry point (removed in PR #130). Session log tracking filters headers internally. |
| 171 | + |
| 172 | +2. **GPS freshness varies by context**: Manual pings tolerate 60s old GPS data, auto pings force fresh acquisition. Check `GPS_WATCH_MAX_AGE_MS` vs `GPS_FRESHNESS_BUFFER_MS`. |
| 173 | + |
| 174 | +3. **Control locking during ping lifecycle** - `sendPing()` disables all controls until API post completes. Must call `unlockPingControls()` in ALL code paths (success/error). |
| 175 | + |
| 176 | +4. **Auto-ping pause/resume** - Manual pings during auto mode pause countdown, resume after completion. Handle in `handleManualPingBlockedDuringAutoMode()`. |
| 177 | + |
| 178 | +5. **Disconnect cleanup order matters**: Flush API queue → Release capacity → Delete channel → Close BLE → Clear timers/GPS/wake locks → Reset state. Out-of-order causes errors. |
| 179 | + |
| 180 | +6. **Tailwind config paths**: Build scans `index.html` and `content/**/*.{js,html}`. Missing paths = missing styles. |
| 181 | + |
| 182 | +7. **Status message visibility race** - Use `immediate=true` for countdown updates, `false` for first display (enforces 500ms minimum). |
| 183 | + |
| 184 | +## Code Style Conventions |
| 185 | + |
| 186 | +- **No frameworks/bundlers** - Vanilla JS with ES6 modules (`import`/`export`) |
| 187 | +- **Functional > Classes** - Most code uses functions + closures (except mc/ library uses classes) |
| 188 | +- **State centralization** - Global `state` object, explicit mutations |
| 189 | +- **Constants at top** - All config in SCREAMING_SNAKE_CASE (intervals, URLs, thresholds) |
| 190 | +- **Async/await** - Preferred over `.then()` chains |
| 191 | +- **Error handling** - Wrap BLE/API calls in try-catch, log with `debugError()` |
| 192 | + |
| 193 | +## Key Files Reference |
| 194 | + |
| 195 | +- `content/wardrive.js:connect()` (line ~2020) - 10-step connection workflow |
| 196 | +- `content/wardrive.js:sendPing()` (line ~2211) - Ping validation & send logic |
| 197 | +- `content/wardrive.js:handleUnifiedRxLogEvent()` (line ~3100) - RX packet handler |
| 198 | +- `content/wardrive.js:flushApiQueue()` (line ~3800) - Batch API POST |
| 199 | +- `content/mc/connection/connection.js` - MeshCore protocol implementation |
| 200 | +- `docs/FLOW_WARDRIVE_API_QUEUE_DIAGRAM.md` - Visual API queue architecture |
| 201 | +- `docs/COVERAGE_TYPES.md` - Coverage block definitions (BIDIR, TX, RX, DEAD, DROP) |
| 202 | + |
| 203 | +## Testing Approach |
| 204 | + |
| 205 | +**No automated tests** - Manual testing only: |
| 206 | +1. **Syntax check**: `node -c content/wardrive.js` |
| 207 | +2. **Desktop testing**: Primary development on Chrome/Chromium desktop |
| 208 | + - Use Chrome DevTools Sensors tab for GPS simulation |
| 209 | + - Mobile device emulation for responsive UI testing |
| 210 | +3. **Debug logging**: Enable via `?debug=true` to trace workflows |
| 211 | +4. **Production validation**: App primarily used on mobile (Android Chrome, iOS Bluefy) |
| 212 | + - Desktop testing sufficient for most development |
| 213 | + - Real device testing with MeshCore companion for final validation |
| 214 | + |
| 215 | +**Mobile-first app, desktop-tested workflow** - Most development happens on desktop with DevTools, but remember users are on phones with real GPS and BLE constraints. |
0 commit comments