diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 0000000..7c2c051 Binary files /dev/null and b/docs/.DS_Store differ diff --git a/docs/admins.md b/docs/admins.md index 47f42e5..41b303f 100755 --- a/docs/admins.md +++ b/docs/admins.md @@ -187,6 +187,8 @@ The Settings tab is organised into collapsible blocks. The ageing and cleanup co - **Enforce Hybrid Mode**: Disables Active mode for wardrivers in your region. If your regions mesh has an issue with dropped packets due to high mesh traffic or many wardrivers, consider enabling this option. *(Mobile app functionality will be available with v1.1.0)* - **Consider Failed DISC as DROP**: When disabled, Discovery pings that do not receive a reply will not appear on the map. When enabled, Discovery pings that do not will receive a reply will display as DROP (red) on the map. - **Minimum Active/Hybrid Mode Interval**: Optionally set the number of seconds between mesh pings for wardrivers in your region. If your regions mesh has an issue with dropped packets due to high mesh traffic or many wardrivers, consider setting a higher minimum interval. *(Mobile app functionality will be available with v1.1.0)* + - **Enforce Smart Pinging**: Locks the app's Smart Pinging on for wardrivers in your region, so auto pings are deferred in squares that already have a recent two-way or discovery result and the held ping goes out at the next square without one. Users cannot turn it off while connected to your zone, and your window replaces their own. Wardrivers still earn 1.5 points per verified deferred square. Requires app v1.4.0 or newer; older apps ignore the setting. + - **Smart Pinging Window (Days)**: How recent a result must be for a square to count as covered: 1, 3, 7, 14 or 30 days. Only applies while Enforce Smart Pinging is on. Otherwise each user's own window (default 14 days) applies. - **Region Message**: Optionally add a message here that will display to map visitors when they click the "Region Info" option. Direct guests to your Discord server, website, etc. Field is plain-text and will automatically convert URLs to clickable links. - **Social Media Links**: Optionally add any number of social media or website links that will display on the "Region Info" window on your regions map. - **MQTT Observers**: Configure the list of letsmesh observers to ingest from. diff --git a/docs/app_connection_guide.md b/docs/app_connection_guide.md index 3118e9f..4cf3678 100644 --- a/docs/app_connection_guide.md +++ b/docs/app_connection_guide.md @@ -150,11 +150,11 @@ If you don't have internet, or the MeshMapper API is in maintenance mode, use ** - Zone validation is skipped (zone chip shows a grey dash) - All ping data (TX, RX, DISC) is saved to local session files - Session files are named by date (e.g., "2026-03-20.json") -- Manage sessions in **Settings > Offline Sessions** +- Manage sessions in **Settings > Data > Offline Sessions** **When you are back online:** -1. Open **Settings > Offline Sessions** +1. Open **Settings > Data > Offline Sessions** 2. Tap upload button next to each session to send to MeshMapper 3. Or download session files for backup diff --git a/docs/app_getting_started.md b/docs/app_getting_started.md index 2470e7a..b856b51 100644 --- a/docs/app_getting_started.md +++ b/docs/app_getting_started.md @@ -48,7 +48,7 @@ It also discloses that your location data is uploaded to the MeshMapper API and After tapping **Continue**, your phone will ask for location permission. Grant "While Using the App" at minimum. !!! warning "iOS Background Location" - If you want to run MeshMapper in the background on iOS (e.g., wardriving with the screen off), you need to manually enable "Background Location" in the MeshMapper Settings tab. Apple restricts apps from requesting background location directly, so the user must enable it themselves. Without this, iOS will throttle or stop GPS updates when the app is not in the foreground. + If you want to run MeshMapper in the background on iOS (e.g., wardriving with the screen off), you need to manually enable "Background Location" under Settings > General in MeshMapper. Apple restricts apps from requesting background location directly, so the user must enable it themselves. Without this, iOS will throttle or stop GPS updates when the app is not in the foreground. --- @@ -104,7 +104,7 @@ Once both are set, tap **Send Ping**: - The app sends a channel message to #wardriving - This message **floods the entire mesh network**, with every repeater relaying it onward -- **Your GPS position is not in the on-air message.** By default the message carries a short anonymous token — your coordinates are sent only to the MeshMapper server over the internet. (You can opt in to broadcasting coordinates on the air via Settings > Ping Settings > Broadcast My Coordinates.) +- **Your GPS position is not in the on-air message.** By default the message carries a short anonymous token, and your coordinates are sent only to the MeshMapper server over the internet. (You can opt in to broadcasting coordinates on the air via Settings > Wardriving > Broadcast My Coordinates.) - If your regional admin has configured a **scope**, the message stays within that region instead - The app listens for **5 seconds** to see which repeaters echoed your message back - On the backend, MeshMapper uses **MQTT observers** that also listen to the #wardriving channel. If an observer receives your message, the backend marks that ping as **bidirectional (bidir)** diff --git a/docs/app_how_it_works.md b/docs/app_how_it_works.md index 300d468..2b48758 100644 --- a/docs/app_how_it_works.md +++ b/docs/app_how_it_works.md @@ -108,6 +108,21 @@ Trace pings target a specific repeater by hex ID: --- +## How Smart Pinging Works + +Smart Pinging is the app's way of not repeating work the map already shows. It is on by default and applies to Hybrid, Passive and Active modes. + +1. **Coverage lookup**: While connected, the app keeps MeshMapper's recent coverage for roughly 500m around you loaded. It uses the same vector tiles the map draws, filtered to two-way (green) and discovery (cyan) results inside your Smart Pinging window. The lookup re-checks after every 100m of movement and refreshes tiles older than 5 minutes at the next 100m. Squares you cover yourself during the session (a heard TX, an answered discovery) are marked covered immediately. +2. **The check**: When an auto ping (TX or discovery) is due, the app looks up the square under your current GPS fix. The square is the cell of your Grid Mode setting (300m, or 100m in Detailed). A recent green or cyan result there means the ping is deferred, and the countdown reads "Deferred". The check runs before the minimum distance rule, so a covered square reads "Deferred" rather than "Skipped". +3. **The hold**: A deferred ping is banked in a single slot. On every GPS fix the app asks whether you have reached a square with no recent coverage and moved at least your minimum ping distance since the last ping of that kind. If so, the banked ping goes out and the interval timer restarts. A later deferral replaces an earlier one, so at most one ping is ever waiting. The regular interval keeps running underneath, so a phone that never reaches a fresh square still tries at its normal cadence. +4. **Fail open**: If the coverage data is not loaded yet, a fetch failed, you are outside a zone, or you are in Offline Mode, the lookup answers "unknown" and the ping is sent as normal. Smart Pinging only ever holds a ping it knows to be redundant. +5. **Credit**: A deferred ping posts no coverage row, so on its own it would cost you the point that ping would have earned. Instead the app reports a small `DEFER` item for each square where it held a ping (one per 300m square per session, whatever your Grid Mode) in the normal upload batch. MeshMapper verifies the square really was covered in its own data, drops any it cannot confirm, and credits the accepted ones at 1.5 points each. Accepted squares also drive the Airtime awards and the Top Airtime Savers leaderboard. + +!!! note + Manual pings, Trace Mode and passive RX listening are never deferred. RX is free coverage, and the other two are you asking for a specific measurement. + +--- + ## Packet Filtering and Validation Every packet goes through a strict validation pipeline before being accepted. If a packet fails any step, it is dropped immediately. @@ -206,7 +221,7 @@ A "carpeater" (car + repeater) is a repeater mounted in/on your vehicle. It will **Two filter methods:** 1. **RSSI threshold**: RSSI equal to or stronger (closer to 0) than -30 dBm → automatically dropped (device is right next to you) -2. **User-configured repeater ID**: Specify your repeater's hex ID in Settings > Filtering > CARpeater Filter. Echoes from that repeater are stripped before upload. +2. **User-configured repeater ID**: Set your repeater's full public key in Settings > Wardriving > CARpeater Filter. Echoes from that repeater are stripped before upload. Both can be adjusted or disabled in Settings for testing. @@ -222,7 +237,7 @@ Each packet carries a "path" showing which repeaters it traveled through, with e **Key details:** -- Configurable in Settings > Radio > TX Bytes (firmware 1.14+ required) +- Configurable in Settings > Wardriving > Radio > TX Bytes (firmware 1.14+ required) - RX auto-detects path size regardless of your TX setting - Regional administrators can require a specific TX path setting in the admin panel diff --git a/docs/app_settings_reference.md b/docs/app_settings_reference.md index 661c5e0..ee843a2 100644 --- a/docs/app_settings_reference.md +++ b/docs/app_settings_reference.md @@ -1,115 +1,159 @@ # Settings Reference -Complete reference for every setting in MeshMapper, organized by section. +Complete reference for every setting in MeshMapper. The Settings tab is a list of folders, and each folder opens its own page. The headings below follow the app: one section per folder, then the groups you see inside it. !!! warning - Some settings are locked while auto-ping is running. A yellow banner appears at the top of the Settings screen when this is the case. Stop auto-ping to change locked settings. + Some settings are locked while auto-ping is running. A yellow banner appears at the top of Settings and on each folder page when this is the case. Stop auto-ping to change locked settings. --- ## General -### Theme +*Appearance, sounds, background location* -- Toggle between **Dark mode** (default) and **Light mode** -- Dark mode recommended for wardriving at night to reduce glare +### Appearance -### Background Location (Mobile only) +#### Theme -- Prompts for "Always" location permission for continuous GPS tracking when the app is backgrounded -- **Android**: Background operation uses a foreground service. Enabling this grants "Always" location permission for improved GPS consistency. -- **iOS**: Required for reliable background wardriving. Without it, iOS may throttle or stop GPS updates when the app is not in the foreground. +- Toggle between **Dark mode** (default) and **Light mode** +- Dark mode recommended for wardriving at night to reduce glare -### Units +#### Units -- **Metric** (km, m) or **Imperial** (mi, ft) +- **Metric** (km, m, default) or **Imperial** (mi, ft) - Affects distance displays throughout the app: zone distances, ping distances, GPS simulator speed -### Sound Notifications +### Sounds + +#### Sound Notifications - Plays sounds on ping events. Sounds follow your phone's **media volume**. - When enabled, three individual sounds can be toggled: - - **Ping Sent** — Sound when a TX ping or discovery is sent - - **Response Received** — Sound when a repeater echo or RX is received - - **Disconnect Alert** — Triple beep when pinging stops unexpectedly (e.g., BLE drop mid-session) + - **Ping Sent**: Sound when a TX ping or discovery is sent + - **Response Received**: Sound when a repeater echo or RX is received + - **Disconnect Alert**: Triple beep when pinging stops unexpectedly (e.g., BLE drop mid-session) - Coexists with other audio (transient focus with ducking on Android, ambient on iOS) - Useful when wardriving with phone mounted out of view +### Location (Mobile only) + +#### Background Location + +- Prompts for "Always" location permission for continuous GPS tracking when the app is backgrounded +- **Android**: Background operation uses a foreground service. Enabling this grants "Always" location permission for improved GPS consistency. +- **iOS**: Required for reliable background wardriving. Without it, iOS may throttle or stop GPS updates when the app is not in the foreground. +- The app cannot take a permission away again, so switching this off opens the system settings for you to change it there + +### Live Activity (iOS only) + +#### Repeater Names on Live Activity + +- Chooses how the Top Heard list is drawn on the Live Activity (Lock Screen and Dynamic Island), CarPlay and Apple Watch +- **On** (default): named rows, one repeater per line +- **Off**: a compact grid that fits more repeaters + +### Exit (Android only) + +#### Close App After Disconnect + +- App automatically exits after disconnecting from your radio +- Disabled by default + +#### Close App + +- Immediately exits the app +- Confirmation dialog. Warns if connected. + --- -## Map Management +## Map + +*Map tiles, coverage overlay, markers* -### Offline Maps (Mobile only) +### Map Tiles + +#### Offline Maps (Mobile only) Download map areas to your device for wardriving without a data connection. Opens the **Offline Maps** screen: -- **Download Area**: Pick a map style (Liberty, Dark, or Light — Satellite is not downloadable), a zoom range, and an area on the map. An estimated tile count is shown before downloading. +- **Download Area**: Pick a map style (Liberty, Dark, or Light; Satellite is not downloadable), a zoom range, and an area on the map. An estimated tile count is shown before downloading. - **Storage**: Shows downloaded areas and the ambient cache (tiles auto-cached while panning), with a configurable storage limit and options to clear or delete. -### Use Downloaded Tiles Only +#### Use Downloaded Tiles Only -- When enabled, the map uses **only** your downloaded areas — no network tile requests at all +- When enabled, the map uses **only** your downloaded areas, with no network tile requests at all - Useful for guaranteed offline operation or saving mobile data -### Coverage Overlay Opacity +### Coverage Overlay + +#### Coverage Overlay Opacity -- Slider (30%–100%) controlling how strongly the community coverage overlay is drawn over the base map +- Slider (30% to 100%, default 70%) controlling how strongly the community coverage overlay is drawn over the base map -### Grid Mode +#### Grid Mode - **Simplified** (default): 300m coverage cells, merged cells, grouped repeaters. Loads faster. - **Detailed**: 100m coverage cells with finer detail and non-grouped repeaters. - Matches the Grid Mode option on the web map +- Also sets the square size [Smart Pinging](#smart-pinging) uses, so what is deferred matches what is painted -### Color Vision +#### Color Vision -- Choose a colour palette optimised for your vision type: Default, Protanopia, Deuteranopia, Tritanopia, or Achromatopsia +- Choose a colour palette optimised for your vision type: Default, Protanopia (red-blind), Deuteranopia (green-blind), Tritanopia (blue-blind), or Achromatopsia (monochrome) - Applies to the coverage overlay and map colours, matching the web map's accessibility palettes -### Map Marker Style +### Markers + +#### Map Marker Style -- Choose the visual style used for ping markers on the map +- Choose the visual style used for ping markers on the map: **Dot** (default), **Outlined Dot**, **Pin**, or **Diamond** -### GPS Marker +#### GPS Marker -- Choose the marker that represents your position (including the "Chomper" style that faces your direction of travel) +- Choose the marker that represents your position: **Arrow** (default), **Car**, **Bike**, **Boat**, **Walk**, **Dog**, or **Chomper** (which faces your direction of travel) -### Top Repeaters on Map +#### Top Repeaters on Map - Shows the **Top Heard** overlay on the map with the best 3 repeaters by SNR from your most recent ping - Disabled by default --- -## Ping Settings +## Wardriving -### Anonymous Mode +*Auto-ping, privacy, CARpeater filter, modes, radio* + +### Privacy + +#### Anonymous Mode - Renames your companion device to **"Anonymous"** on the mesh (requires a clean disconnect to reset your node name) - Changing while connected triggers a brief reconnection - Confirmation dialog when enabling or disabling while connected - Cannot change while auto-ping is running -### Broadcast My Coordinates +#### Broadcast My Coordinates -- **Disabled by default.** By default, your TX pings do **not** contain your GPS position on the air — they carry a short anonymous token instead, and your coordinates travel only to the MeshMapper server over the internet. Anyone listening on the wardriving channel sees the token, not your location. +- **Disabled by default.** By default, your TX pings do **not** contain your GPS position on the air. They carry a short anonymous token instead, and your coordinates travel only to the MeshMapper server over the internet. Anyone listening on the wardriving channel sees the token, not your location. - Enabling this appends your real GPS coordinates to the on-air ping message, visible to anyone with the community channel key. - Leave this off unless you specifically want your live position visible on the mesh (e.g., so local mesh users can follow your drive in real time). -### Auto-Ping Interval +### Auto-Ping + +#### Auto-Ping Interval How frequently pings are sent in Active, Hybrid, and Trace modes: -- **15 seconds** — Fast (more coverage, causes more mesh load) -- **30 seconds** — Normal (balanced coverage and mesh load, default) -- **60 seconds** — Slow (less coverage, little mesh load) +- **15 seconds**: Fast (more coverage, causes more mesh load) +- **30 seconds**: Normal (balanced coverage and mesh load, default) +- **60 seconds**: Slow (less coverage, little mesh load) - Cannot be changed during auto-ping -- Regional admin may enforce a minimum interval (you cannot choose faster) +- Regional admin may enforce a minimum interval. Faster choices are greyed out and marked "Set by Regional Admin". !!! note Does not affect Passive Mode (fixed 30-second discovery interval). In Hybrid Mode, the effective interval between channel messages is doubled since discovery requests alternate with TX. -### Min Ping Distance +#### Min Ping Distance Minimum distance you must move before the next auto-ping. Prevents spamming from a stationary position. @@ -120,32 +164,74 @@ Minimum distance you must move before the next auto-ping. Prevents spamming from !!! note Does not apply to manual pings. Cannot be changed during auto-ping. -### Auto-Stop After Idle +#### Smart Pinging + +Defers auto pings in squares that already have recent coverage, so your airtime goes where it adds something new. See [Smart Pinging](app_wardriving_modes.md#smart-pinging) for how it behaves on the road. + +- **Enabled by default** +- Tap the **(i)** beside the switch for a short explanation inside the app +- **Defer pings in squares covered within**: the window, in days, that makes a square count as covered. Enter any whole number from **1 to 365**. Default **14 days**. Shown only while the switch is on. +- Applies to Hybrid, Passive and Active modes. Never affects manual pings, Trace Mode or passive RX listening. +- Deferred squares still earn leaderboard points (1.5 each) once MeshMapper verifies them +- May be enforced by regional admin (shown in amber). When enforced, the switch is locked on and the window is the region's. +- Cannot be changed during auto-ping + +#### Auto-Stop After Idle - Automatically stops auto-ping after **30 minutes without GPS movement** - Prevents unnecessary transmissions and saves battery - Enabled by default - Cannot be changed during auto-ping ---- +### CARpeater + +A "CARpeater" is a repeater mounted in your vehicle or carried with you. Without filtering, every ping would show it as "heard" with an extremely strong signal and the coverage map would fill with false data. Three layers deal with this: your own CARpeater's key, the region's shared list, and the RSSI failsafe. + +#### CARpeater Filter + +Strips your own CARpeater from results. Switching it on for the first time opens the **My CARpeater** dialog, and a **My CARpeater** row stays under the switch while it is on. + +- Enter the full **public key** of your CARpeater (64 hex characters), or tap **Choose from repeater list** to pick it from the repeaters the app already knows. The key is checked before it can be saved. +- **Pass-through**: an echo or RX packet that came through your CARpeater is stripped of that hop and the repeater behind it is credited instead. A packet that only reached your CARpeater is dropped, and so is a discovery response from it. +- Your key is shared with MeshMapper so that every wardriver in the region filters your CARpeater too (see Regional CARpeaters below) +- Cannot be changed during auto-ping + +!!! note "Upgrading from an older version" + Earlier versions accepted a short hex ID prefix. That prefix is no longer used. If you had one set, the app asks for the full key after your next connect, with a button to this page. "Not now" asks again after the next connect; "I don't use a CARpeater" stops asking. + +#### Regional CARpeaters -## Modes +- Shows how many CARpeaters have been shared for your region, with a list (name and key) when there are any. Your own is marked "Mine". +- These are always filtered and cannot be turned off: someone else's CARpeater is in someone else's car, so neither it nor the repeater behind it may be credited +- The list is refreshed from MeshMapper on every connect. Offline Mode keeps the last copy. -### Flood Traffic +#### Disable RSSI Filter + +By default, the app drops any packet with RSSI equal to or stronger (closer to 0) than -30 dBm because a signal that strong almost certainly came from a co-located repeater and is not meaningful coverage data. Only disable this if you are certain no co-located repeater is within range. If disabled while a CARpeater is present, your device will report false coverage data to the MeshMapper community map, degrading accuracy for everyone. + +- Default: Drops packets with RSSI of -30 dBm or stronger (carpeater threshold) +- Enabling allows **all signal strengths** through +- Confirmation dialog warns about community map impact before enabling +- Cannot be changed during auto-ping + +### Modes + +#### Flood Traffic - Shows or hides the **Active Mode**, **Hybrid Mode**, and manual **Send Ping** controls (everything that sends flood channel messages) -- With Flood Traffic off, only Passive and Trace modes are available -- May be locked off by your regional admin if the region has disabled flood wardriving traffic +- **Off by default.** On a fresh install only Passive and Trace modes appear on the Map tab. Turn this on to wardrive with channel messages. +- May be locked off by your regional admin if the region has disabled flood wardriving traffic (shown with a blue note) +- Cannot be changed during auto-ping -### Hybrid Mode +#### Hybrid Mode - Alternates between TX channel messages and discovery requests each interval - Produces richer data with **50% fewer channel messages** (less mesh flooding) -- Enabled by default across all regions +- Enabled by default across all regions. Tap the **(i)** beside the switch for how the interval timing works. - May be locked by regional admin (shown in amber when enforced) - Cannot be changed during auto-ping -### Discovery Drop +#### Discovery Drop - Counts discovery requests with **no response** as "failed pings" reported to the API - Helps identify dead zones for network planning @@ -155,39 +241,15 @@ Minimum distance you must move before the next auto-ping. Prevents spamming from - Confirmation dialog before enabling - Cannot be changed during auto-ping ---- - -## Filtering - -### CARpeater Filter - -If you're wardriving with a repeater mounted in your vehicle or nearby ("CARpeater"), enable this filter so that direct echoes from your own repeater are stripped from results. Without it, every ping would show your co-located repeater as "heard" with an extremely strong signal, polluting the coverage map with false data. - -- Enter the full **6-digit hex ID** (3 bytes) of your co-located repeater (e.g., "A3B2FF") -- The app automatically truncates to match your region's hop byte size (1, 2, or 3 bytes) -- Multi-hop packets through your CARpeater are stripped to report the underlying repeater -- Cannot be changed during auto-ping - -### Disable RSSI Filter - -By default, the app drops any packet with RSSI equal to or stronger (closer to 0) than -30 dBm because a signal that strong almost certainly came from a co-located repeater and is not meaningful coverage data. Only disable this if you are certain no co-located repeater is within range. If disabled while a CARpeater is present, your device will report false coverage data to the MeshMapper community map, degrading accuracy for everyone. +### Radio -- Default: Drops packets with RSSI ≥ -30 dBm (carpeater threshold) -- Enabling allows **all signal strengths** through -- Confirmation dialog warns about community map impact before enabling -- Cannot be changed during auto-ping - ---- - -## Radio - -### TX Bytes +#### TX Bytes Repeater ID size in TX/RX path hops: -- **1 byte** — 256 unique IDs, standard for most networks -- **2 bytes** — ~65K unique IDs, reduces collisions -- **3 bytes** — ~16M unique IDs, maximum resolution +- **1 byte**: 256 unique IDs, standard for most networks +- **2 bytes**: about 65K unique IDs, reduces collisions +- **3 bytes**: about 16M unique IDs, maximum resolution !!! warning Requires both your companion device and repeaters to be on firmware **1.14+**. Only change this if you understand what you're doing, or if your regional admin has enforced a value. RX always auto-detects the sender's byte size regardless of your TX setting. @@ -202,7 +264,7 @@ Repeater ID size in TX/RX path hops: !!! note Applied to your radio during connection, restored on clean disconnect. -### Trace Bytes +#### Trace Bytes Repeater ID size for trace path requests: @@ -212,9 +274,9 @@ This is separate from TX Bytes because traces use a different encoding in the Me | TX/RX (simple counter) | Trace (bitshift encoding) | |---|---| -| Mode 0 → 1 byte | Mode 0 → 1 byte | -| Mode 1 → 2 bytes | Mode 1 → 2 bytes | -| Mode 2 → 3 bytes | Mode 2 → 4 bytes | +| Mode 0: 1 byte | Mode 0: 1 byte | +| Mode 1: 2 bytes | Mode 1: 2 bytes | +| Mode 2: 3 bytes | Mode 2: 4 bytes | !!! warning 3-byte traces are not supported by the MeshCore protocol. When your region uses 3-byte TX paths, set Trace Bytes to 4. @@ -228,76 +290,124 @@ This is separate from TX Bytes because traces use a different encoding in the Me - "Connect to radio to configure" (amber) when disconnected - Cannot be changed during auto-ping -### Delete Channel on Disconnect +#### Delete Channel on Disconnect -- **Enabled** (default): Removes #wardriving channel from your radio on disconnect. Keeps radio clean. +- **Enabled** (default): Removes the #wardriving channel from your radio on disconnect. Keeps the radio clean. - **Disabled**: Channel remains. Slightly faster reconnection since it doesn't need to be recreated. --- ## Data -### Queued Pings +*Queued pings, map markers, offline sessions* + +### Current Session -Shows items waiting to be uploaded. Two actions: +#### Queued Pings -- **Force Upload**: Immediately upload all queued items -- **Clear Queue**: Permanently delete all queued pings. Confirmation dialog included. +Shows how many items are waiting to be uploaded, with two actions beside the count: -### Clear Map Markers +- **Force upload**: Immediately upload all queued items +- **Clear queue**: Permanently delete all queued pings. Confirmation dialog included. + +#### Clear Map Markers - Removes all TX, RX, discovery, and trace markers from the map display - Does not affect uploaded data or the upload queue ---- - -## Offline Sessions +### Offline Sessions Sessions recorded in Offline Mode. Each session shows: - Filename (date-based) -- Creation timestamp -- Ping count -- Device info +- Ping count and date +- Device name **Actions per session:** -- **Upload**: Send to MeshMapper servers -- **Download**: Save raw JSON to your device (via the system share sheet on mobile) +- **Download**: Save the raw JSON to your device (via the system share sheet on mobile). Always available. +- **Upload**: Send to MeshMapper servers. Shown until the session has been uploaded. - **Delete**: Remove from local storage +After an upload the session shows an "Uploaded" line with where its pings were placed. Tap it for the **Upload Summary**: the number of pings credited to each region, and any that were dropped for being more than 50 km outside every region. + +--- + +## MeshMapper Account (Mobile only) + +*Sign in to link your radios* + +Signs you in to your [My MeshMapper](portal.md) account and links your radios to it, so their wardriving counts toward your account. Linking is best-effort and never affects a connection. + +### Account + +- **Sign in to MyMeshMapper**: Opens the portal sign-in page in your system browser. Finish signing in there and return to the app; the app never sees your password. +- Once signed in, the row shows your display name and username +- **Sign Out**: Signs the app out. Your linked devices stay on the server. +- The **refresh** button in the top bar re-reads your account. It is rate limited, and the app says how long to wait if you refresh too often. + +### Overview + +Shown once you are signed in, when the server provides it: your **Points**, **Grid squares** and number of **Companions**, plus your award badges (tap one for its description). The totals are the same ones the portal's Overview tab shows, summed across all your linked radios. + +### Devices + +- **This Device**: The connected radio. **Link now** has the radio sign a one-time challenge to prove it is yours; **Unlink** removes it. Needs a connected radio and is locked during auto-ping. +- Below it, every companion linked to your account, with its name, key and points +- **Re-enable Link Prompts**: Appears after you have declined a link prompt, or a radio was recorded as unable to sign. Clears those records so the app asks again. + +!!! note + After you connect a radio that is not yet linked, the app offers to link it. It asks at most once per radio per app session, and never while auto-ping is running. + --- ## API Endpoints -### MeshMapper API +*MeshMapper and custom endpoints* + +### MeshMapper -- Always active — this is where your wardriving data goes. +#### MeshMapper API -### Custom API Endpoint +- Always active. This is where your wardriving data goes. + +### Custom Endpoint + +#### Custom API Endpoint Forward your wardrive data to a third-party HTTPS endpoint **in addition to** MeshMapper: +- A **Third-Party Data Sharing** notice must be accepted the first time it is enabled - **Endpoint URL** and **API Key** fields (HTTPS is required; the key is sent as an `X-API-Key` header) - **Include Contact Key**: Optionally share your device's public key prefix with the endpoint (on by default, can be disabled) - **Import from Clipboard**: Paste a `meshmapper://custom-api?...` configuration link from an endpoint operator to auto-fill both fields -- Best-effort and fire-and-forget — a broken custom endpoint never affects your MeshMapper uploads +- Best-effort and fire-and-forget. A broken custom endpoint never affects your MeshMapper uploads. +- Everything MeshMapper receives is forwarded, including [Smart Pinging](app_wardriving_modes.md#smart-pinging) deferrals See the [Third Party API guide](app_third_party_api.md) for the full payload contract (aimed at endpoint developers). --- -## About +## Apple Watch (iOS only) -### App Name and Version +*Inspect pairing and delivery state* -- Shows "MeshMapper" and current version -- Tap version to copy to clipboard +This folder appears once an Apple Watch has been paired with your phone, and stays after an unpair, because that is when it is most useful. It opens the **Watch Connectivity** page for diagnosing a watch app that is not updating: -### Submit Feedback +- **Sync gate**: whether the phone is currently allowed to send to the watch, and why not +- **Last successful send**, **Last availability change** and **Last send outcome** +- **Refresh** re-reads the state -- Opens bug report dialog to report bugs or request features -- Can attach debug log files if logging is enabled (select which files to include) +--- + +## About & Support + +*Version, feedback, debug logs* + +### About + +- **MeshMapper**: App name and tagline +- **Version**: Tap to copy the version to the clipboard. Seven quick taps unlock the [Developer Tools](#developer-tools) folder. ### Links @@ -306,24 +416,14 @@ See the [Third Party API guide](app_third_party_api.md) for the full payload con - **Community**: Built with contributions from the Greater Ottawa Mesh Radio Enthusiasts community - **Buy us a coffee**: Support MeshMapper development (not shown on iOS) ---- - -## Exit (Android only) +### Support -### Close App After Disconnect - -- App automatically exits after disconnecting from your radio +#### Submit Feedback -### Close App - -- Immediately exits the app -- Confirmation dialog. Warns if connected. - ---- - -## Debug (Mobile only) +- Opens the bug report dialog to report bugs or request features +- Can attach debug log files if logging is enabled (select which files to include) -### Debug Logs +#### Debug Logs (Mobile only) - Writes detailed debug logs to files on your device - Orange "LOGGING" badge when active @@ -335,5 +435,26 @@ See the [Third Party API guide](app_third_party_api.md) for the full payload con - **Log file list**: Date, size, active status - **View**: In-app log viewer - **Share**: System share sheet -- **Upload**: Send to MeshMapper team for analysis +- **Upload**: Send to the MeshMapper team for analysis - **Delete All**: Remove all stored log files + +--- + +## Developer Tools + +*GPS simulator* + +Hidden until unlocked by tapping the version seven times on About & Support. + +### Developer Mode + +- Switch it off to hide the Developer Tools folder again + +### GPS Simulator + +Replaces the phone's GPS with a simulated position, for testing without leaving the desk. An orange "SIMULATED" badge shows while it is on. + +- **Simulation Speed** and **Simulation Altitude** sliders +- **Movement Pattern**: Straight Line, Circle, or Random Walk +- **Load Route File**: Follow a KML or GPX route instead of a pattern. Shows the route name and point count once loaded, with a button to clear it. +- **Reset Position**: Back to the start of the route, or to downtown Ottawa when no route is loaded diff --git a/docs/app_tabs.md b/docs/app_tabs.md index 84b0703..1a5b90d 100644 --- a/docs/app_tabs.md +++ b/docs/app_tabs.md @@ -95,7 +95,7 @@ These show the **backend's view** of coverage, combining data from all wardriver - **DEAD** (brown): A repeater heard it, but no other radio received the repeat - **DROP** (red): No repeats heard AND did not reach a backend observer. Also includes failed discovery requests if the region has "Count DISC as failed" enabled, meaning the backend tracks a failed discovery as no coverage at that location. -The overlay renders from the same vector coverage tiles as the web map, using your selected **Grid Mode** (Simplified 300m or Detailed 100m — see Settings > Map Management) and Color Vision palette. After a successful upload, your own newly-mapped cells refresh in place within about 10 seconds — you can watch your coverage appear as you drive. +The overlay renders from the same vector coverage tiles as the web map, using your selected **Grid Mode** (Simplified 300m or Detailed 100m, see Settings > Map) and Color Vision palette. After a successful upload, your own newly-mapped cells refresh in place within about 10 seconds, so you can watch your coverage appear as you drive. **Tap to inspect:** @@ -302,7 +302,7 @@ For a detailed walkthrough of the connection process, see the [Connection Guide] ## Settings Tab -The Settings tab contains all user preferences and configuration options. Settings are organized into sections: General, Map Management, Ping Settings, Modes, Filtering, Radio, Data, Offline Sessions, API Endpoints, About, Exit (Android only), and Debug. +The Settings tab contains all user preferences and configuration options. It is a list of folders, each opening its own page: General, Map, Wardriving, Data, MeshMapper Account (mobile only), API Endpoints, Apple Watch (iOS, once a watch has been paired), About & Support, and Developer Tools (hidden until unlocked). Some settings are locked while auto-ping is running to prevent mid-session changes that could affect data consistency. A yellow banner at the top indicates when settings are locked. diff --git a/docs/app_third_party_api.md b/docs/app_third_party_api.md index 4704edd..b29d993 100644 --- a/docs/app_third_party_api.md +++ b/docs/app_third_party_api.md @@ -32,12 +32,13 @@ Every ping object contains a `type` field that determines which additional field | Field | Type | Description | |-------|------|-------------| -| `type` | `string` | Ping type: `"TX"`, `"RX"`, `"DISC"`, or `"TRACE"` | +| `type` | `string` | Ping type: `"TX"`, `"RX"`, `"DISC"`, `"TRACE"`, or `"DEFER"`. A `DEFER` carries only the common `lat`, `lon`, `timestamp`, `contact` and `iata` fields plus `held` (see below); it has no `external_antenna`, `noisefloor`, `altitude` or `power`. | | `lat` | `number` | Latitude (WGS84, decimal degrees) | | `lon` | `number` | Longitude (WGS84, decimal degrees) | | `timestamp` | `integer` | Unix timestamp in seconds | | `external_antenna` | `boolean` | Whether an external antenna is connected to the device | | `noisefloor` | `integer\|null` | Ambient noise floor in dBm (e.g., -103). Null if unavailable. | +| `altitude` | `integer\|absent` | Altitude of the fix in whole meters (e.g., `123`). Absent when the phone did not know its altitude. iOS reports height above mean sea level. Android usually reports height above the WGS84 ellipsoid, but Android 14 and later substitutes mean sea level when the fix carries it, so one device can report either. The two references can differ by up to about 100 m. | | `power` | `string\|null` | Radio TX power formatted as `"X.Xw"` (e.g., `"0.3w"`, `"1.0w"`, `"2.0w"`). Null if unavailable. | | `contact` | `string\|absent` | First 8 hex chars of the wardriver's MeshCore device public key (e.g., `"D873B1F2"`). Only present when the user enables "Include Contact Key" in settings. Useful for cross-referencing with MQTT observer data. | | `iata` | `string\|absent` | MeshMapper zone code (e.g., `"RDU"`, `"MSP"`, `"YOW"`). Present when the wardriver is in a zone. | @@ -58,6 +59,7 @@ A transmitted ping broadcast on the wardriving channel, with repeater echo resul "lat": 45.26974, "lon": -75.77746, "noisefloor": -103, + "altitude": 84, "heard_repeats": "4e(12.25),77(8.50)", "timestamp": 1768762843, "external_antenna": false, @@ -75,6 +77,7 @@ A transmitted ping broadcast on the wardriving channel, with repeater echo resul "lat": 45.27001, "lon": -75.77802, "noisefloor": -101, + "altitude": 86, "heard_repeats": "None", "timestamp": 1768762873, "external_antenna": false, @@ -192,6 +195,102 @@ A targeted zero-hop trace to a specific repeater. } ``` +### DEFER (type: "DEFER") + +A square where the app's smart pinging held a TX ping or a discovery request because MeshMapper already had recent coverage there. The app reports it so MeshMapper can credit the square; you receive it because it may help a mapper keeping its own coverage. + +**A deferral is unverified.** MeshMapper checks each one against its own coverage data and silently discards any it cannot confirm, but the batch answer does not say which items were kept, and the app forwards the whole batch after the upload succeeds. Treat a `DEFER` as "the app believed this square was covered", not as a confirmed observation. + +| Field | Type | Description | +|-------|------|-------------| +| `held` | `string` | Which kind of ping was held: `"tx"` (a channel ping) or `"disc"` (a discovery request). | + +The `external_antenna`, `noisefloor`, `altitude` and `power` fields are not present on a `DEFER`. At most one `DEFER` is sent per 300 m square per MeshMapper session. + +**Example:** + +```json +{ + "type": "DEFER", + "lat": 45.26974, + "lon": -75.77746, + "timestamp": 1757400000, + "held": "tx", + "contact": "D873B1F2", + "iata": "YOW" +} +``` + +## Batch Examples + +A batch is whatever the app uploaded to MeshMapper in that round, so one request can mix every type above. `DEFER` items only appear from app version 1.4.0 onward, and only while the user has Smart Pinging on (the default) in Active, Passive or Hybrid mode, so your endpoint must accept batches both with and without them. Dispatch on `type` and ignore any value you do not handle rather than rejecting the batch: a `4xx` is shown to the user as an error. + +**Batch without a DEFER** (a TX ping and a passive RX observation): + +```json +{ + "data": [ + { + "type": "TX", + "lat": 45.26974, + "lon": -75.77746, + "noisefloor": -103, + "altitude": 84, + "heard_repeats": "4e(12.25),77(8.50)", + "timestamp": 1768762843, + "external_antenna": false, + "power": "0.3w", + "contact": "D873B1F2", + "iata": "YOW" + }, + { + "type": "RX", + "lat": 45.26950, + "lon": -75.77700, + "noisefloor": -105, + "heard_repeats": "4e(12.00)", + "timestamp": 1768762900, + "external_antenna": false, + "power": "0.3w", + "contact": "D873B1F2", + "iata": "YOW" + } + ] +} +``` + +**Batch with a DEFER** (the next TX ping was held because the square already had recent coverage, while passive RX logging carried on): + +```json +{ + "data": [ + { + "type": "DEFER", + "lat": 45.27210, + "lon": -75.78120, + "timestamp": 1768762933, + "held": "tx", + "contact": "D873B1F2", + "iata": "YOW" + }, + { + "type": "RX", + "lat": 45.27222, + "lon": -75.78140, + "noisefloor": -104, + "heard_repeats": "77(9.75)", + "timestamp": 1768762941, + "external_antenna": false, + "power": "0.3w", + "contact": "D873B1F2", + "iata": "YOW" + } + ] +} +``` + +Note that the `DEFER` has no `noisefloor`, `altitude`, `external_antenna` or `power`, while the `RX` beside it does. + ## Expected Response Your endpoint should return any `2xx` HTTP status code on success. The response body is ignored by MeshMapper. @@ -227,11 +326,11 @@ meshmapper://custom-api?url=data.myproject.org/ingest/wardrive&key=sk_live_abc12 The user copies this link, opens MeshMapper Settings > API Endpoints, and taps "Import from Clipboard." Both fields are populated instantly. - ## Security Notes - **HTTPS required**: MeshMapper validates that the configured URL uses HTTPS. HTTP endpoints are rejected at the settings level. - **API key in header**: The user-configured API key is sent as `X-API-Key` header, not in the request body. +- **No MeshMapper credentials**: The MeshMapper API key and session ID are never included in forwarded requests. You receive only the raw ping data. - **Contact key is opt-in**: The `contact` field (device public key prefix) is controlled by the user via "Include Contact Key" toggle. It defaults to ON but can be disabled. - **Fire-and-forget**: Custom API errors never affect MeshMapper's primary data submission. A broken custom endpoint cannot disrupt wardriving. @@ -241,3 +340,10 @@ The user copies this link, opens MeshMapper Settings > API Endpoints, and taps " - **Batch size**: 1-50 ping objects per request (typically 1-10). - **Session duration**: Wardriving sessions commonly last 30 minutes to several hours. - **Concurrent users**: Plan for multiple users if distributing your endpoint URL. Each user sends independently. + +## Why `meshmapper://` links are paste-only + +The `meshmapper://custom-api?...` format is deliberately **not** registered as +an OS URL scheme. Tapping one does nothing; it has to be copied and imported +from Settings. The app registers `meshmapper-auth://callback` instead (portal +sign-in) precisely so that claiming a scheme never hijacks these config links. diff --git a/docs/app_troubleshooting.md b/docs/app_troubleshooting.md index d5f607b..286b072 100644 --- a/docs/app_troubleshooting.md +++ b/docs/app_troubleshooting.md @@ -178,7 +178,7 @@ This is **normal behavior**: **Solutions:** -- Enable in Settings > Ping Settings > Sound Notifications +- Enable in Settings > General > Sound Notifications - Check phone volume and ringer mode ### Audio hangs or freezes @@ -212,10 +212,10 @@ This is **normal behavior**: To capture detailed logs for a bug report: -1. Go to **Settings > Debug** +1. Go to **Settings > About & Support > Debug Logs** 2. Enable **Debug Logs** (orange "LOGGING" badge confirms) 3. Reproduce the issue -4. Use **Submit Feedback** (Settings > About) or the **Upload** button in Debug section +4. Use **Submit Feedback** (Settings > About & Support) or the **Upload** button in the Debug Logs section Logs include timestamped entries for BLE communication, GPS events, ping lifecycle, API calls, and more. @@ -223,7 +223,7 @@ Logs include timestamped entries for BLE communication, GPS events, ping lifecyc ## Reporting Bugs -1. Go to **Settings > About > Submit Feedback** +1. Go to **Settings > About & Support > Submit Feedback** 2. Describe the issue (what you expected vs what happened) 3. Optionally enable "Upload debug logs" and select which log files to include 4. Submit — a confirmation toast appears with a "View" link to track your report diff --git a/docs/app_wardriving_modes.md b/docs/app_wardriving_modes.md index 8c7b385..102a916 100644 --- a/docs/app_wardriving_modes.md +++ b/docs/app_wardriving_modes.md @@ -29,7 +29,7 @@ Controls lock during the 5-second window and API upload. Hybrid Mode is the **recommended default** for wardriving. It alternates between channel messages (TX) and discovery requests at your configured interval. -**To start:** Tap the **Hybrid Mode** button in the Controls panel on the Map tab. (Enabled by default. If disabled in Settings, this button shows as "Active Mode" instead.) +**To start:** Tap the **Hybrid Mode** button in the Controls panel on the Map tab. (Hybrid is on by default. The button only appears while **Flood Traffic** is on under Settings > Wardriving > Modes, which is off on a fresh install. If Hybrid Mode is switched off there, this button shows as "Active Mode" instead.) **What happens each interval (alternating):** @@ -78,7 +78,7 @@ No channel messages (no mesh flooding at all). Sends **discovery requests** ever ## Active Mode !!! warning "Legacy mode" - Hybrid Mode has replaced Active Mode as the default and is recommended for all wardriving. Active Mode is kept for backward compatibility but Hybrid produces richer data with less mesh traffic. To use Active Mode, disable Hybrid Mode in Settings > Modes. + Hybrid Mode has replaced Active Mode as the default and is recommended for all wardriving. Active Mode is kept for backward compatibility but Hybrid produces richer data with less mesh traffic. To use Active Mode, disable Hybrid Mode in Settings > Wardriving > Modes. Sends only channel messages (no discovery requests) at a regular interval (15, 30, or 60 seconds). @@ -112,6 +112,35 @@ Targets a **specific repeater** by hex ID for focused signal testing. --- +## Smart Pinging + +Smart Pinging holds back auto pings in squares that MeshMapper has already mapped recently, so your airtime goes where it adds something new. It is **on by default** and applies to Hybrid, Passive and Active modes. + +**What happens:** + +1. While you are connected, the app keeps MeshMapper's recent coverage for the area around you loaded. +2. When an auto ping is due in a square that already has a recent two-way (green) or discovery (cyan) result, the ping is **deferred** instead of sent. The countdown reads **"Deferred"** while it waits. +3. The deferred ping is kept, not dropped. As soon as you reach a square with no recent coverage (and have moved your minimum ping distance), it goes out and the interval restarts. +4. Only one ping is ever held. If the next interval is deferred too, it takes the place of the one waiting. + +**What counts as covered:** a square with a green or cyan result inside your Smart Pinging window (default 14 days). Squares follow your [Grid Mode](app_settings_reference.md#grid-mode) setting, so what is deferred is exactly what is already painted on the map. + +**Never deferred:** + +- Manual pings +- Trace Mode +- Passive listening to other mesh traffic (RX), which is free coverage +- Anywhere the coverage data cannot be loaded (no network, Offline Mode, outside a zone). The ping simply goes out. + +!!! note "Deferred is not Skipped" + A ping that fails the minimum distance rule reads "Skipped" and is dropped. A deferred ping reads "Deferred" and is still owed. A square that is both covered and too close reads "Deferred". + +**You keep your points.** Every square where a ping was held is reported to MeshMapper, checked against the region's own coverage data, and credited at **1.5 points** once verified (once per 300m square per session). Verified squares also count toward the Airtime awards and the Top Airtime Savers leaderboard. See [Top Airtime Savers](leaderboards.md#top-airtime-savers). + +To turn Smart Pinging off or change the window, see [Smart Pinging](app_settings_reference.md#smart-pinging) in the Settings Reference. Regional admins can enforce it for their zone, in which case the switch is locked on. + +--- + ## TX Capacity Limits Regional admins set a **maximum number of active TX wardrivers** per zone (for example, 5). This prevents too many users from flooding the mesh simultaneously. @@ -171,7 +200,7 @@ Regardless of mode, all data follows the same pipeline: ## Sound Notifications -If enabled (Settings > Ping Settings > Sound Notifications): +If enabled (Settings > General > Sound Notifications): - **TX sent or Discovery sent:** Transmitted packet sound - **Repeater echo or RX received:** Received packet sound diff --git a/docs/awards.md b/docs/awards.md index ccfbc61..ebeb966 100644 --- a/docs/awards.md +++ b/docs/awards.md @@ -33,6 +33,9 @@ These are granted automatically by the system based on wardriving milestones: | **Explorer 1** | Map 1,000 or more unique grid squares | | **Explorer 2** | Map 5,000 or more unique grid squares | | **Explorer 3** | Map 10,000 or more unique grid squares | +| **Airtime Saver** | 250 or more verified squares where Smart Pinging held a ping | +| **Airtime God** | 2,500 or more verified squares where Smart Pinging held a ping | +| **Airtime Legend** | 10,000 or more verified squares where Smart Pinging held a ping | | **Global Leader** | Rank in the top 10 on the global leaderboard (all-time, weekly, or top explorers) | !!! info "Update Interval" diff --git a/docs/faq.md b/docs/faq.md index b9a838e..fd9b9e1 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -49,7 +49,7 @@ Yes. The MeshMapper companion app is the primary way to submit wardriving data. It is available for both Android and iOS. See [Getting Started](https://wiki.meshmapper.net/app_getting_started) for setup instructions. ??? question "Does the wardriving app broadcast my location on the mesh?" - Not by default. TX pings sent on the #wardriving channel carry a short anonymous token instead of coordinates — your GPS position travels only to the MeshMapper server over the internet. Anyone listening on the channel sees the token, not where you are. If you *want* your live position visible on the air (e.g., so local mesh users can follow your drive), enable **Broadcast My Coordinates** in the app's Ping Settings. + Not by default. TX pings sent on the #wardriving channel carry a short anonymous token instead of coordinates, and your GPS position travels only to the MeshMapper server over the internet. Anyone listening on the channel sees the token, not where you are. If you *want* your live position visible on the air (e.g., so local mesh users can follow your drive), enable **Broadcast My Coordinates** under Settings > Wardriving in the app. ??? question "Can I view or delete the data I have contributed?" Yes. Create an account on the [My MeshMapper portal](https://wiki.meshmapper.net/portal/), link your companion device (a quick cryptographic proof over USB or Bluetooth), and you can view your sessions, see your own pings on the map, set your leaderboard display name, and delete some or all of your contributed data. @@ -57,6 +57,12 @@ ??? question "Why isn't my recent data showing on the leaderboard?" Leaderboards and profile statistics are regenerated about once a day, so new contributions can take up to 24 hours to appear. The coverage map itself updates in near-real-time. +??? question "Why does the app show Deferred instead of sending a ping?" + Smart Pinging is holding that ping because the square you are in already has recent coverage on the map. The ping is kept, not dropped: it goes out the moment you reach a square with nothing recent, and you are credited for the square you crossed without transmitting. It is on by default. See [Smart Pinging](app_wardriving_modes.md#smart-pinging), or turn it off under Settings > Wardriving in the app. + +??? question "Do I lose leaderboard points when Smart Pinging holds a ping?" + No. Each square where a ping was held is reported to MeshMapper, checked against the region's own coverage data, and credited at 1.5 points once verified. Verified squares also count toward the Airtime Saver, Airtime God and Airtime Legend awards and the Top Airtime Savers board. Like the rest of the leaderboard, the credit appears after the next daily update. + --- ## Mobile App diff --git a/docs/leaderboards.md b/docs/leaderboards.md index 2207a82..ce34318 100755 --- a/docs/leaderboards.md +++ b/docs/leaderboards.md @@ -20,7 +20,7 @@ At the top of the page, you will find high-level metrics for the current region. ## User Leaderboards -User rankings are based on the number of valid data points contributed. 1 Ping = 1 Point. +User rankings are based on the number of valid data points contributed. 1 Ping = 1 Point. A square where the app's Smart Pinging held a ping counts for 1.5 points once verified, in the same totals (see [Top Airtime Savers](#top-airtime-savers)). - **Top Contributors (7 Days)**: A rolling window of activity over the last week. This is useful for seeing who is currently active in the community. - **All Time Legends**: The total accumulation of contributions since the region was onboarded. @@ -34,6 +34,9 @@ This leaderboard rewards **exploration** — covering new ground rather than re- | **2nd** | **Silver** Number | | **3rd** | **Bronze** Number | +### Top Airtime Savers +This leaderboard rewards **restraint**. When the app's [Smart Pinging](app_wardriving_modes.md#smart-pinging) holds a ping in a square that already has recent coverage, the square is reported, verified against the region's own coverage data, and credited at **1.5 points**. Each square counts once per session on the 300m grid, whatever the user's Grid Mode setting. This board ranks users by those points alone; the same points are also included in the All Time and 7 Day totals above. + ## Repeater Leaderboards These tables highlight the performance of the infrastructure itself. @@ -57,6 +60,7 @@ The [Global Leaderboard](https://meshmapper.net/global_leaderboard.php) aggregat - **Global Stats**: Combined totals across all regions — data points, ping breakdowns, repeater count, contributors, total grid squares, active regions, and observer counts (with a per-broker breakdown). - **Top Contributors (7 Days)** and **All Time Legends**: Cross-region user rankings with each user's primary region shown. - **Top Explorers**: Aggregated first-mapper grid square counts across all regions. + - **Top Airtime Savers**: Cross-region Smart Pinging credit, ranked by points. - **Region Rankings**: **Most Repeaters**, **Most Grid Squares**, **Most Data Points**, and **Most Contributors** — regions ranked against each other. - **Best Repeaters (Ping Count)** and **Best Repeaters (Max Range)**: Repeater rankings drawn from every region, with links back to the originating regional map. The Ping Count table includes unique grid square counts alongside total ping counts — click the column headers to sort by either metric.