diff --git a/README.md b/README.md index 5608007..f988131 100755 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ -# MeshMapper_Wiki \ No newline at end of file +# MeshMapper Wiki + +Source for [wiki.meshmapper.net](https://wiki.meshmapper.net), the documentation for MeshMapper, built with [MkDocs Material](https://squidfunk.github.io/mkdocs-material/). + +## Editing + +Pages live in `docs/` and the sidebar is defined by `nav` in `mkdocs.yml`. Link between pages with relative links (e.g. `[Backbone](backbone.md)`) so broken links are caught by the build. + +## Building Locally + +```bash +pip install mkdocs-material mkdocs-macros-plugin pyyaml mkdocs-glightbox pymdown-extensions +mkdocs serve # preview at http://127.0.0.1:8000 +mkdocs build --strict # same check the deploy runs +``` + +Pushing to `main` builds and deploys the site to GitHub Pages. diff --git a/docs/administratorlist.md b/docs/administratorlist.md index 5905a1b..6e48cab 100644 --- a/docs/administratorlist.md +++ b/docs/administratorlist.md @@ -23,7 +23,7 @@ Tag the MeshMapper bot in the MeshMapper Discord server: @MeshMapper !admins YOW ``` -Or just ask in natural language — `@MeshMapper who runs YOW?` works too. The bot replies with the region's administrators and their contact information. See [Bot Commands](botcommands.md) for more. +Or just ask in natural language — `@MeshMapper who runs YOW?` works too. The bot replies with the names of the region's administrators. For contact details, use **Region Info** on the region's map. See [Bot Commands](botcommands.md) for more. ## Still Can't Reach Anyone? @@ -37,4 +37,6 @@ If a region's administrators are unavailable or unresponsive, tag a `@Moderator` * **Global Administrator**: Moderator access across all regions. * **Region Administrator**: Access to specific geographic regions. +Region administrators can invite another admin for their region from the **Admins** tab of the admin panel. The invite is emailed and expires after 7 days. + Want to become an administrator for your region? See the [FAQ](faq.md#administration) and [Onboarding](onboarding.md) pages. diff --git a/docs/admins.md b/docs/admins.md index 7ae9523..21e2086 100755 --- a/docs/admins.md +++ b/docs/admins.md @@ -1,488 +1,547 @@ -# Admin Portal +# Admin Panel -The **MeshMapper Admin Portal** is a restricted area designed for region maintainers to manage data integrity, configure system settings, and monitor the health of a regions map. +The **MeshMapper Admin Panel** is where region administrators keep their region's data clean, change its settings, and check the health of its map. ## Access & Permissions -Access to the Admin Portal is strictly controlled. It is not available to general users. +The Admin Panel is only for region administrators. - - **How to get access:** If the region has an administrator, ask them for an invite. If it has no administrator, ask a Moderator in the MeshMapper Discord for help with access. See [Finding Your Region's Administrators](administratorlist.md). + - **Getting access:** If the region has an administrator, ask them for an invite. If it has none, ask a Moderator in the MeshMapper Discord. See [Finding Your Region's Administrators](administratorlist.md). + - **Signing in:** Go to **admin.meshmapper.net** and sign in with your MeshMapper account (username or email, plus password), or click **Sign in with Discord**. It's the same account you use for the [portal](portal.md). If you've lost your password, use **Forgot password?**. -## Dashboard & Active Sessions +The sidebar lists the tabs in this order: **Overview**, **Coverage**, **Repeaters**, **CARpeaters**, **Companions**, **Sessions**, **Administrators**, **Tools**, **History**, **Alerts**, **Observers**, **Settings** and **User Settings**. It also has **Go to Map** and **Switch Region**. -Upon logging in, the dashboard presents a live view of **Active Sessions**. +## Overview - - **Real-time Monitoring:** See who is currently wardriving in your region. - - **Capacity Management:** Displays the current slot usage (e.g., 2/5 slots). - - **Kick User:** Admins can forcibly end a session if a user is stuck or consuming a slot unnecessarily. +The first tab you see after signing in. + + - **Region Statistics:** Total Data Points, Bidirectional, TX Only, RX Only, Discovery, Dead, Dropped, Active Repeaters, Est. Coverage and Contributors. Click **Refresh** to update them. + - **Active Sessions:** Who is wardriving in your region right now, with Status, Last Active and Pings (click **Calc** to count them). + - **Capacity:** Shows **Active**, **Transmitting** (slots used out of slots available) and **Passive** sessions. Group panels show **Group TX slots**. + - **Kick:** Ends a session that is stuck or holding a slot it doesn't need. ## Data Management -The portal is divided into several tabs for managing different data types. +The next few tabs manage your region's data: pings, repeaters, CARpeaters, companions and sessions. ### Coverage -This tab allows granular control over individual data points (pings). - - **Search:** Find pings by User, Time, or Repeater ID. - - **Edit:** Correct erroneous data (e.g., if a user forgot to flag "External Antenna" or entered the wrong power level). - - **Delete:** Remove individual bad data points. - - **Debug:** If "Debug Mode" was enabled during the drive, a **Debug** button appears, allowing admins to inspect the raw JSON payload received from the device. - - **Bulk Select & Delete:** Use the checkboxes on each row (or the "Select All" checkbox in the header) to select multiple pings. A toolbar will appear at the bottom of the screen with an option to **Delete Selected**. +Every coverage point (ping) in your region. + + - **Search:** By Name, Time/Date, Lat/Lon, Block Code (paste a `P-` code from the map), Via (repeater), Heard Repeats or Offline Uploads. You can also filter by status. + - **Row details:** An icon opens the ping on the map. Pings uploaded later from the app's offline mode show an **OFFLINE** badge. Tags show the radio preset and altitude when known. + - **Delete:** Removes a single bad ping. + - **Debug:** If the ping was sent with Debug Mode on, a **Debug** button shows the raw data from the device. + - **Bulk delete:** Tick rows (or the header box to select all), then click **Delete Selected**. + - **Export CSV:** Downloads the current results. + +!!! info "Fixing ping details" + Region admins can't edit a single ping. To fix details such as power or external antenna, use **Bulk Update Pings** in the [Tools tab](#maintenance-tools). ### Repeaters -Manage the repeaters database. -If an unknown repeater appears, first check whether an observer has received an advert with a valid name. A repeater heard only in wardriving discovery can appear as a **Ghost** without a name or fixed location. An admin can add or correct its record in the **Repeaters** tab, then check whether it is **Pending**, **Inactive**, or **Excluded**. Do not assign a guessed location to a moving device. +Your region's repeater list. + +If an unknown repeater shows up, first check whether an observer has heard an advert from it with a valid name. A repeater heard only through wardriving discovery is a **Ghost**: it has no name or fixed location. You can add or correct its record here. Don't give a guessed location to a device that moves. + +On a group map, a repeater can come from any member region. Check the Region column before editing it. When a repeater moves, its next advert updates its position unless **Lock GPS Coordinates** is on. Old pings don't move with it. + +#### Statuses + + - **Active:** Shown on the map and leaderboards, and linked to coverage pings. + - **Disabled:** Hidden from the map and leaderboards, but kept in the list. + - **Inactive:** No advert has reached MeshMapper within **Repeater Inactive After** (default 30 days), so it's hidden from the map. The record is kept, and it goes back to Active on its own at its next advert through an observer. Wardrive pings alone won't bring it back. See [Repeater Lifecycle & Cleanup](#repeater-lifecycle-cleanup). + - **Ambiguous:** Its ID matches another repeater's, so MeshMapper can't tell which one a ping went through. It shows as a **red** icon on the map, and coverage isn't credited to it (except **Discovery** pings, which carry the full key). See [the collision rules](duplicaterepeaterid.md#the-rules). + - **Pending** (shown as a pill): Found, but waiting for approval. Only used when **New Repeaters Enter Pending State** is on. Pending repeaters aren't on the map and don't collect coverage. Approve one by editing it and setting its status to **Active**, or use **Review Pending Repeaters** in the Alerts tab. Pending repeaters that nobody reviews are sorted out automatically; see [Pending repeater resolution](#pending-repeater-resolution). + +!!! warning "You can't force an Ambiguous repeater to Active" + MeshMapper checks for ID collisions again at every advert, so setting an Ambiguous repeater to **Active** won't stick. To fix it, one of the repeaters has to change its ID. See [Duplicate Repeater IDs](duplicaterepeaterid.md). + + A **Disabled** or **Inactive** repeater is left out of this check. If one side of a collision is gone for good, set it to Disabled and its partner goes back to Active at its next advert. -A repeater can appear on a grouped map because that map reads the group's member regions. Its region record is separate from the region your browser is showing. Check the region column before editing it. After a repeater moves, a new advert can update its position unless **Lock GPS Coordinates** is on. Earlier pings do not move with it. +#### Adding and editing - - **Add/Edit:** Manually register repeaters or update their details (Name, Location, Power, Hop Bytes). - - **Status Control:** - - **Active:** The default state. The repeater is visible on the map, included in leaderboards, and actively associating with coverage pings. - - **Disabled:** The repeater is hidden from the public map and leaderboards but remains in the database for historical purposes. - - **Inactive:** The repeater hasn't sent an advert within the region's **Repeater Inactive After** window (default 30 days) and has been removed from the map. This is non-destructive — the record is retained and returns to Active automatically the next time the repeater adverts and an observer relays it to MeshMapper. Wardrive pings alone will not bring it back. See [Repeater Lifecycle & Cleanup](#repeater-lifecycle-cleanup). - - **Pending:** The repeater has been discovered but is awaiting approval. Pending repeaters are **not** visible on the map and do not associate with coverage data. This state is only used when the "New Repeaters Enter Pending State" setting is enabled for the region. Admins can approve a pending repeater by editing it and setting its status to **Active**. Once a pending repeater has existed for 3× the stale timer it is resolved automatically — approved if it has been heard within 1× the stale timer, deleted if it has not. See [Pending repeater resolution](#pending-repeater-resolution). - - **Excluded:** The repeater is flagged as a duplicate. It appears as a **Red** icon on the map. Coverage data is **not** associated with this repeater to prevent skewing statistics (with the exception of **DISCOVERY** type pings). An Excluded repeater that goes silent is eventually marked **Inactive** like any other, which releases the repeater it was colliding with. + - **Add Repeater:** Name, Advert Bytes (1, 2 or 3), Public ID, ID, Lat, Lon, Power, Status and Bypass Auto Delete. + - **Edit:** Name, location, power, status, Hardware, Antenna, Height above ground (m), Power source and Site note (shown publicly), plus: + - **Lock GPS Coordinates:** New adverts won't change its location. Use it when the GPS set on the repeater is wrong. + - **Bypass Auto Delete:** Every automatic cleanup skips this repeater. It won't be marked Inactive, won't be removed as a stale Pending repeater, and won't be removed by [Repeater Retention / Auto-Delete](#repeater-retention-auto-delete-days). Good for seasonal or remote repeaters you want kept on the map. + - **Administrators:** People who logged in to the repeater as admin from the app. Add one by public key or exact companion name. + - **Radio presets:** Presets the repeater was heard on. Add one as `freq,bw,sf`. Removing one only hides it until the repeater is heard on that preset again. - !!! warning "Duplicate Repeater Persistence" - **You cannot force a repeater with a colliding ID to remain Active.** - - If a repeater is flagged as **Excluded** due to an ID collision, manually setting it back to **Active** is futile. The moment MeshMapper receives a new advert or ping from that repeater, the collision detection logic will trigger again, and it will immediately revert to **Excluded**. In addition, setting a repeaters status to **Disabled** does not bypass collision detection logic. - - This is a safety mechanism designed to protect the integrity of the map's data. To resolve this, one of the colliding repeaters must change its ID. If a repeater that was once a duplicate is no longer physically on the mesh, deleting the repeater will ensure collision detection logic will not trigger for surviving repeaters. +!!! warning "Lock GPS Coordinates" + Locking the location of a repeater that moves will put its coverage in the wrong place. - - **Ping Calc:** A tool to recalculate the total number of pings a repeater has handled. - - **Neighbours Cleanup:** Reset the neighbours list for any repeater in the region. Useful for clearing stale or incorrect neighbour associations. - - **Notes:** Clicking the note icon will allow you to optionally add a note to the repeater. On multiregion admin panels, if a repeater belongs to multiple single regions, notes will be combined and edits will be saved to the individual regions. - - **Lock GPS Coordinates:** Enabling this setting will prevent new adverts from a repeater from updating its location. This can be used in instances where the GPS coordinates set on the repeater are incorrect and need to be manually overridden. - - **Bypass Auto Delete:** When enabled on a repeater, every automatic cleanup routine will skip it entirely. The repeater will not be marked inactive, will not be removed as a stale pending repeater, and will not be removed by the [Repeater Retention / Auto-Delete](#repeater-retention-auto-delete-days) purge. This is useful for repeaters that are known to be offline for extended periods but should remain on the map (e.g. seasonal deployments, repeaters in remote locations with intermittent connectivity). - - **Bulk Select & Edit/Delete:** Use the checkboxes on each row (or the "Select All" checkbox in the header) to select multiple repeaters. A toolbar will appear at the bottom of the screen with options to **Edit Selected** or **Delete Selected**. Bulk edit allows you to change Status, Power, Lock GPS, and Notes for all selected repeaters at once — each field has an "Apply" checkbox so you only change the fields you intend to. Works across multi-region admin panels. +#### Finding and managing repeaters - !!! warning "Bulk Notes" - Bulk editing the Notes field will **overwrite** existing notes for all selected repeaters. + - **Filters:** Location (All, No Location (0,0), Out of Boundary) and claim (All, Claimed, Unclaimed). The table shows each repeater's **Bytes** and whether it's in or out of your boundary. + - **Select Offline (n):** Selects every offline repeater at once. + - **Mark as CARpeater:** Tags a repeater as riding in a car. See [CARpeaters](#carpeaters). + - **Ping counts:** Click **Calc** on a row, or **Load All Ping Counts**. + - **Notes:** Click the note icon to add a note. On a group panel, notes for a repeater that's in several regions are shown together and saved to each region. + - **Export CSV:** Downloads the list. + - **Bulk Edit:** Tick rows, then change Status, Power, Lock GPS and Notes for all of them at once. Each field has an **Apply** checkbox, so only ticked fields change. Bulk editing Notes **overwrites** existing notes. You can also delete the selected repeaters. + - **Neighbours:** To clear a repeater's neighbour list, use **Reset Neighbours** in the [Tools tab](#maintenance-tools). - !!! warning "Data Inaccuracy Warning" +!!! warning "Deleting doesn't fix a duplicate ID" + A deleted repeater comes back at its next advert. Deleting won't fix an ID collision while the repeater is still on the air. - Enabling "Lock GPS Coordinates" for a repeater that can or will physically move locations will result in inaccurate data. Use with caution. +!!! info "Blank name adverts" + Adverts with a blank name are rejected, so nothing is added or updated. If a working repeater isn't showing up, check that its name is set. -!!! info "Blank Name Adverts" - If a repeater advert is received with a blank or missing name, MeshMapper will silently reject it — no record will be created or updated. This is a data quality safeguard. If a repeater is not appearing on the map despite being active on the mesh, verify that its name is set correctly on the device. +### CARpeaters + +A CARpeater is a repeater riding in a wardriver's car. Pings heard through it would make coverage look far bigger than it is, so apps in your region drop packets heard through a CARpeater. + + - **Add CARpeater:** Enter the repeater's public key. You can also use **Mark as CARpeater** on the Repeaters tab. + - **Columns:** Public Key, Resolves To, Shares Prefix With, Reporters, First Reported, Last Reported and Auths. + - **Delete:** Removes the tag. + +Tags that haven't been reported for **CARpeater Retention (Days)** (default 90) are removed. See [CARpeater Retention](#carpeater-retention-days). ### Companions -Manage the "Phonebook" of known companions. - - **Identity:** Map a Public ID (e.g., `12345678...`) to a human-readable Name. - - **Blocking:** Set a companion's status to **Blocked** to prevent them from uploading data to the map. - - **Notes:** Clicking the note icon will allow you to optionally add a note to the companion. On multiregion admin panels, if a repeater belongs to multiple single regions, notes will be combined and edits will be saved to the individual regions. - - **Bulk Select & Edit/Delete:** Same multi-select functionality as repeaters. Bulk edit allows you to change Status and Notes for all selected companions at once. +Your region's list of known companions. + + - **Add Companion:** Add a companion by public ID and give it a name. The **Type** column shows what kind of device it is. + - **Status:** **Active**, **Inactive** or **Blocked**. A Blocked companion can't upload data to the map. + - **Notes:** Click the note icon to add a note. On a group panel, notes for a companion that's in several regions are shown together and saved to each region. + - **Bulk Edit:** Tick rows, then change Status and Notes for all of them at once. + - **Delete:** The delete window has **Also delete its N coverage points in this region**, ticked by default. The deletion is logged so it can be undone. ### Sessions -A historical log of all wardriving sessions. - - **Metadata:** View details about the device used (App Version, Hardware Model, etc.). - - **Cleanup:** Options to delete just the pings from a session (keeping the record) or wipe the session entirely. +Every wardriving session in your region. + + - **Columns:** Who, Session ID, Mode (Standard or Offline), Status, Started, Active Time, Ping Count and Actions. + - **Metadata:** Shows details of the device used, such as app version and hardware model. + - **🗑️ Pings Only:** Deletes the session's pings but keeps the session. + - **×:** Deletes the session and its pings. ### Users -Manage user identities to group multiple contacts. - - **Leaderboard Grouping:** Associate multiple contacts/companions under a single User identity. This ensures that all contributions from these devices are aggregated together on the leaderboards. The name that will display on the leaderboards is that of the selected Main Companion. - - **Future Functionality:** Currently, this feature is for administrative grouping only. However, plans are in place to expand this into a full Contributor Portal, allowing users to log in, view their personal statistics, and manage the data they have contributed to MeshMapper. There are some fields (like Username) that exist for this purpose but are not yet implemented. +The Users tab has been retired. Wardrivers now link their own companions to their MeshMapper account in the [portal](portal.md), which becomes their leaderboard identity. -### Observers +## Administrators -Monitor the MQTT observers that are feeding data into your region. +Everyone with admin access to your region. Each listed admin shows as **Active**, with their contact info. On a group panel, you also see which member regions each admin has. -#### Summary Cards +**Pending Invites** lists invites that haven't been accepted yet: Invitee, Region, Invited By and Expires. Use **Resend** to send one again, or **×** to revoke it. -Four metric cards are displayed at the top of the tab: +### Adding a New Administrator - - **Total**: The total number of unique observers seen. - - **Online**: Observers that have reported data within the stale threshold (configured in Settings). - - **Stale**: Observers that have reported within the last 7 days but are beyond the stale threshold. - - **Offline**: Observers with no activity in the last 7 days. + 1. Click **Invite Admin**. + 2. In **Invite an administrator**, enter their **Email** and pick a **Region Assignment**. + 3. Click **Send invite**. -#### Table Columns +MeshMapper emails an invite tied to that address. It expires after 7 days. If the email fails, the panel shows a link you can pass on yourself. - - **Observer ID**: The unique identifier of the observer node. - - **Region**: *(Multi-region groups only)* Which sub-region(s) the observer belongs to. - - **Status**: The observer's current state — **Online** (green), **Stale** (orange), or **Offline** (red). - - **Last Heard**: How long ago the observer last reported data. - - **Pings**: The number of coverage pings submitted through this observer. - - **Repeaters**: The number of repeater adverts heard by this observer. - - **Companions**: The number of companion adverts observed. - - **LetsMesh MQTT**: Indicates whether this observer has contributed data via the LetsMesh broker. - - **MeshMapper MQTT**: Indicates whether this observer has contributed data via the MeshMapper in-house broker. +### Accepting an Invite -!!! info "MQTT Brokers" - Only 1 broker per observer is required to submit data to MeshMapper. Data received from both brokers will aggregate. +Open the invite with the matching email or Discord account. Sign in to your MeshMapper account, or create one, then accept the invite. Sign in to the admin panel with that same account. - - **Notifications**: A toggle to mute or unmute offline Discord notifications for this observer. Muting suppresses notifications only — data collection is unaffected. - - **Remove**: Administrators can remove stale or inactive observers from the list. Note that if the observer starts sending packets again, it will automatically be re-added. +Forgot your password? Use **Forgot password?** on the sign-in page or the [portal](portal.md). If you use Discord to sign in, click **Sign in with Discord**. The bot doesn't send new passwords. -!!! info "Observer Data Source" - Observer data is aggregated from coverage, repeater, and companion records over the last 30 days. Observers will appear here automatically once they begin reporting data. +## Maintenance Tools -### Administrators +The **Tools** tab changes many pings at once. **Use with care.** Every tool has **Analyze & Preview**, so you see what will change before you confirm. -The **Administrators** tab displays all admin accounts that have been granted access to your region and allows you to invite new administrators. + - **Replace Repeater:** Moves an old repeater's pings to another repeater, within a From/To date range. Useful when a repeater gets a new ID or new hardware. **Find removed repeaters** helps you pick one that's no longer in the list. Ping positions aren't moved, so run **Reassociate Repeater** afterwards. + - **Bulk Delete / Scrub Pings:** Deletes pings from one companion or all companions, in a date range or **All time**. Pick a repeater to remove just that repeater from the pings instead of deleting them. + - **Bulk Update Pings:** Changes details on many pings. **Companion** is required and **Session ID** is optional. You can set a **New Companion** (rename), **New Power** and **New Ext. Ant**. There's no date filter. + *Example:* set every ping from companion "Tom_Mobile" in session `20241221-0005` to External Antenna = YES. + - **Reassociate Repeater:** Re-links pings to a repeater that was missing when they came in, or that had the wrong GPS. Pings already within about 100 m of the right spot are skipped, and so are pings where the repeater ID is ambiguous. + - **Reset Neighbours:** Clears the neighbour list of one repeater, or of **All Repeaters (Full Reset)**. - - **Name:** The username of the administrator account. - - **Contact:** The contact information on file for the administrator (e.g., Discord handle, email). - - **Region:** On multiregion admin panels, each administrator's entry will display which sub-regions they have been granted access to. - - **Status:** Shows whether access is active or the invitation is still pending. +!!! warning "Check the location first" + Reassociating pings to a repeater in the wrong place puts coverage in the wrong place. Make sure the repeater's GPS is right before running it. -#### Adding a New Administrator +## History -In your region's **Administrators** tab, click **+ Add Administrator**, enter the person's email address, and select a region you administer. MeshMapper emails an invite bound to that address. If email delivery fails, the panel shows a link you can pass to that person. The invite expires after seven days. A global administrator can also grant a region directly to an existing verified MeshMapper account. +**Admin Activity History** is a log of every admin action in your region: Time, User, IP, Action and Details. -Pending invites can be revoked or resent from the panel. +## Alerts -#### Registration +**Alerts & Warnings** lists things that need a look. If there's nothing, it shows **All clear!** -Open the invite with the matching email or Discord account. Sign in to your existing MeshMapper account, or create one and choose your own password. Accept the invite to add the region. Sign in to the admin panel with that same account. + - **Repeater Clock Alerts:** Repeaters whose clock is more than 120 seconds off, among those that adverted in the last 7 days. A wrong clock can affect routing. Tick **Only show in-boundary repeaters** to hide the rest. + - **Ambiguous Public IDs Detected:** Repeaters that share an ID, listed by **Collision Group**. **MB Capable** tags show which ones can use multi-byte IDs. See [Duplicate Repeater IDs](duplicaterepeaterid.md). + - **Pending Repeaters:** Repeaters waiting for approval. Click **Review Pending Repeaters**. + - **Suspicious Live Sessions:** Sessions with pings moving faster than any ground vehicle, usually a device on a plane. Each row shows who, session ID, start time, top speed and ping count, with a **🗺️ Map** link. **Delete** the session to remove its pings, or **Dismiss** it if the speed was real (a train, for example). Dismissed sessions are kept in a list and can be brought back with **Restore**. + - **Pending Repeater Links:** Pings held because their repeater is too far away. See below. -Forgot your password? Use **Forgot password** on the [portal](portal.md). If your account uses Discord sign-in, choose **Sign in with Discord**. The bot does not issue replacement credentials. +### Pending Repeater Links -## Maintenance Tools +Created by the [Pending Link Distance](#pending-link-distance-km) setting: a ping's repeater ID matched exactly one registered repeater, but it's farther away than your set distance. + +The pings **stay on the map**. They're just not linked to a repeater until you decide. Nothing is deleted or hidden. + +#### Reading the evidence + +Each row gives you what you need to decide: + + - **The matched repeater:** ID, name, region and distance. + - **What was actually heard on air:** The short ID the radio really reported. It's often shorter than the matched ID, and that's the key point: the extra bytes came from MeshMapper's lookup, not from the radio. + - **Nearby ghosts:** Unregistered devices answering discovery in the area. **Strong matches** start with the exact ID that was heard; if there is one, the pings almost certainly belong to it and the panel says so. **Weak matches** share only the first byte and are shown faded. + - **The held pings:** Date, session, heard ID, coordinates, and a **🗺️ Map** link to each ping. + +#### Your three choices + + - **Link to repeater:** You know that repeater really reaches this area. The pings link to its current position, and future far pings for this ID link automatically. + - **Leave unlinked:** The likely case. The pings stay on the map, linked to no repeater. New far pings will alert again. + - **Leave unlinked + suppress:** The same, but future far pings are held quietly without a new alert. Use it once you've confirmed there's a local unregistered device. + +With more than one row you also get **Suppress all**. Suppressed IDs sit in their own list with held-ping counts and can be restored one at a time or all at once. + +!!! info "Suppression clears itself" + MeshMapper keeps watching each ID. If a local repeater with that ID registers, the distant one moves or is deleted, or a new ghost appears, suppression clears and you're alerted again. The same goes for a confirmed link. + +!!! warning "When linking is refused" + - **Unplaced repeater:** It has no usable position, so linking would put the pings in a meaningless place. Place it on the map first. + - **Newly ambiguous:** More than one repeater now matches that ID, so linking would be a guess. Check that ID's repeaters first. + +Admins with the **Pending Repeater Link** notification on get a daily reminder. Each ID notifies once, and again only if its situation changes. + +## Observers + +The MQTT observers feeding data into your region. -The **Tools** tab contains powerful utilities for bulk operations. **Use with caution.** +!!! info "Connecting an observer" + Connect your observers to the [MeshMapper MQTT broker](mqtt-main.md). MeshMapper also collects from LetsMesh, but that isn't MeshMapper infrastructure. - - **Replace Repeater**: - - Useful when a repeater changes its ID or is replaced by new hardware. - - Scans the entire database and updates all historical pings to point to the new ID. - - - **Bulk Delete Pings**: - - Remove all data for a specific companion or session within a specific time range. +**Summary cards** at the top: - - **Bulk Update**: - - Mass-edit attributes for a set of pings. - - *Example:* Change all pings from companion "Tom_Mobile" on "Dec 25th" to have "External Antenna = YES". + - **Total:** Every observer seen. + - **Online:** Heard within your region's **Stale Repeater Age**. + - **Stale:** Heard within the last 7 days, but not within Stale Repeater Age. + - **Offline:** Not heard in the last 7 days. - - **Reassociate Repeater**: - - Reassociate pings to a repeater that was missing from the map at the time of ingestion, or whose GPS coordinates were incorrect. - - Select a repeater and click "Analyze & Preview" to see how many pings would be affected. The tool detects ID collisions automatically — if the repeater's short ID collides with another active repeater, only DISC pings (matched by full public key) will be processed. - - Pings that already have the correct coordinates (within ~100m) are skipped. +**Table columns:** - !!! warning "Use With Caution" - Reassociating pings to the wrong repeater location will result in misrepresented data. Always verify the repeater's GPS coordinates are correct before running this tool. + - **Observer:** Its name and ID. + - **Region:** *(Groups only)* Which member region(s) it belongs to. + - **Status:** Online, Stale or Offline, with how long ago it was last heard. + - **Pings**, **Repeaters**, **Companions:** How many coverage pings, repeater adverts and companion adverts came through it. + - **Brokers:** One badge per broker. A badge is coloured when that broker heard the observer in the last 7 days, with the last-heard time below it. + - **Notifications:** Mutes or unmutes offline alerts for this observer. Muting only stops alerts; data still comes in. + - **Action:** **Remove** takes an old observer off the list. If it starts sending again, it comes back on its own. ## System Settings -Configure how the map behaves for your region. +The **Settings** tab is split into blocks: **Public Display**, **Repeaters, Neighbours & Scopes**, **Wardriving**, **MQTT Brokers & Observers**, **Data Sources**, **Notifications** and **Region Boundary**. Click **Save All Settings** when you're done. -The Settings tab is organised into collapsible blocks. The ageing and cleanup controls all live under **Repeaters & Data Integrity** — see [Repeater Lifecycle & Cleanup](#repeater-lifecycle-cleanup) and [Coverage Ping Settings](#coverage-ping-settings) below. +### Public Display - - **Max Session Capacity**: Limit the number of simultaneous wardrivers to prevent mesh congestion. - - **Disable All Flood Traffic**: Disables Active and Hybrid modes in the mobile app entirely — users in your region can only passively wardrive. When enabled, Max Session Capacity is forced to 0 and greyed out. - - **Hide Companion Names**: Toggle privacy mode for the public map. Also disables the companion filter for map traffic — the public map's Filter → User field is shown disabled with an explanation. - - **Hop Bytes**: Configure the region's repeater identification byte length — 1-byte (256 IDs), 2-byte (65K IDs), or 3-byte (16M IDs). When set to 2 or 3-byte, companion devices connecting to wardrive sessions are automatically configured to use the enforced hop byte length. In 1-byte regions, MeshMapper passively detects which repeaters support multi-byte by watching packets and only confirmed repeaters will show multi-byte IDs on the map. Collision detection, coverage mapping, and leaderboards all respect the configured hop byte length. Changing the byte mode automatically recalculates repeater collisions and updates affected repeaters to Active status. Requires MeshCore firmware v1.14.0+. - - **Single Observer Mode**: Enable this if your region relies on a single MQTT ingestor to prevent repeaters from being flagged as "Stale" too quickly. A region in Single Observer Mode is skipped entirely by the nightly repeater cleanup — repeaters are never marked stale, never marked inactive, and never auto-deleted. (Ghost cleanup still runs, since it only touches the heard-only catalog.) - - **Public Channels**: Define which channels are treated as public traffic. - - **Regions/Scopes**: If your region uses MeshCore Regions/Scopes, define it here. If not, leave the default scope of "*". - - **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. - - **Subscribe to all local observers**: This gives a region the option to either define which observers make up their mesh and exclude everything else (when off), or by toggling this on, listen for packets from any connected observer in the IATA. Turning this off and defining which observers to use could be helpful in cases where someone has fired up an observer and connected it with an IATA, but in reality its far away from the actual region and not contributing to the mesh. + - **Region Message:** Shown to map visitors when they open **Region Info**. Use it to point people to your Discord server or website. Plain text up to 500 characters; links become clickable. Not shown on regions that are part of a group. + - **Social Media Links:** Any number of social media or website links, shown in **Region Info**. -### Repeater Lifecycle & Cleanup +### Repeaters, Neighbours & Scopes -Everything that ages, hides, or deletes data lives in the **Repeaters & Data Integrity** block of the Settings tab. A repeater goes quiet, gets flagged, gets hidden, and — only if you opt in — eventually gets deleted. + - **Stale Repeater Age**, **Repeater Inactive After (Days)**, **Repeater Retention / Auto-Delete (Days)**, **Ghost Retention (Days)** and **CARpeater Retention (Days)**: see [Repeater Lifecycle & Cleanup](#repeater-lifecycle-cleanup). + - **Pending Link Distance (km)** and **Stale Ping Cleanup**: see [Coverage Ping Settings](#coverage-ping-settings). + - **Neighbour links:** How long a neighbour link stays after it was last seen: **Inferred, days** (default 7), **Reported, days** (30) and **Uploaded, days** (0). **0** means never delete it on age. Links between repeaters farther apart than **Max link distance, km** (default 250) are dropped. + - **Scopes to Monitor:** Extra scope names to look for in the traffic MeshMapper hears, one per row, saved in lowercase. Your Wardriving Scope and scopes your repeaters report are included automatically, so most regions can leave this empty. + - **Mesh Scopes retention:** How long each kind of scope sighting is kept: **Seen forwarding**, **Reported by observers** and **Uploaded from the app**, in days (default 60; **0** means never delete). + - **New Repeaters Enter Pending State** and **Disable Duplicate ID Detection Logic**: see below. -Cleanup runs once a night, so changes you save here take effect on the next run rather than immediately. +#### Repeater Lifecycle & Cleanup -!!! warning "“Heard” means an advert, not a wardrive" - These timers only reset when the repeater sends an **advert that reaches MeshMapper through an MQTT observer**. +These settings decide when a quiet repeater is flagged, hidden and (only if you turn it on) deleted. Cleanup runs once a night, so changes take effect at the next run. - Wardriving past a repeater records its pings normally, but does **not** reset its clock — it will still go stale, go Inactive, and be deleted on schedule. A repeater that is transmitting fine but has no observer in range will age off the map anyway. +!!! warning "\"Heard\" means an advert, not a wardrive" + These timers only reset when the repeater sends an **advert that reaches MeshMapper through an MQTT observer**. - Ghosts are the exception — they run on wardrive discovery. See [Ghost Retention](#ghost-retention-days). + Wardriving past a repeater records pings as normal, but does **not** reset its clock. A repeater that works fine but has no observer in range will still age off the map. -#### The lifecycle at a glance + Ghosts are the exception: they run on wardrive discovery. See [Ghost Retention](#ghost-retention-days). -If the region is set to the defaults, this is what happens to a repeater that stops adverting at **day 0**: +With the default settings, this is what happens to a repeater that stops adverting on **day 0**: | Elapsed | What happens | Setting | | --- | --- | --- | | 24 hours | Flagged **stale** on the map. Still Active, still collects pings. | Stale Repeater Age | -| 30 days | Marked **Inactive** and hidden from the map. Reversible — returns to Active when it adverts again. | Repeater Inactive After | +| 30 days | Marked **Inactive** and hidden from the map. Comes back when it adverts again. | Repeater Inactive After | | Never | Permanently deleted. **Off by default.** | Repeater Retention / Auto-Delete | -Ghosts run on their own clock and age out after 30 days. +Ghosts have their own clock and age out after 30 days. Pending repeaters follow their own rules; see [Pending repeater resolution](#pending-repeater-resolution). -Pending repeaters aren't on this timeline at all — see [Pending repeater resolution](#pending-repeater-resolution). +!!! tip "Keep one repeater no matter what" + **Bypass Auto Delete** on a repeater (Repeaters tab) exempts it from every rule in this section. #### Stale Repeater Age (Hours) -**Default: 24. Always on. Non-destructive.** +**Default: 24. Always on. Doesn't delete anything.** -Hours without an advert before a repeater is flagged stale on the map. It stays Active and still collects pings — this is a visual warning only. +Hours without an advert before a repeater is flagged stale on the map. It stays Active and still collects pings; this is only a visual warning. It's also how long a repeater's radio preset tag holds, and how long an observer counts as Online. -The value also sets the **3×** threshold (72 hours by default) used by [pending repeater resolution](#pending-repeater-resolution) below. +It also sets the **3×** point (72 hours by default) used by [pending repeater resolution](#pending-repeater-resolution). -Lower it for a map that reacts quickly to outages; raise it if your repeaters advert infrequently and healthy ones keep getting flagged. +Lower it for a map that reacts quickly to outages. Raise it if your repeaters advert rarely and healthy ones keep getting flagged. ##### Pending repeater resolution -Applies only when **New Repeaters Enter Pending State** is on. This clock starts when the repeater was first added, not when it went quiet. +Only applies when **New Repeaters Enter Pending State** is on. This clock starts when the repeater was first added, not when it went quiet. Once a pending repeater is **3× the stale age** old, MeshMapper decides based on whether it adverted within **1×** the stale age: - - **Adverted recently** → approved to Active. - - **Hasn't** → deleted. + - **Adverted recently:** approved to Active. + - **Didn't:** deleted. !!! example With Stale Repeater Age = 24h, pending repeaters are judged at 72 hours old: - - Added Monday, still adverting Thursday → **approved**. - - Added Monday, went silent Tuesday → **deleted**. - - Added yesterday → not judged yet, whatever it's doing. + - Added Monday, still adverting Thursday: **approved**. + - Added Monday, went silent Tuesday: **deleted**. + - Added yesterday: not judged yet. The two numbers differ on purpose: 72h decides *when* it's judged, 24h decides *which way*. -A repeater with **Bypass Auto Delete** is never deleted here, but can still be auto-approved. +A repeater with **Bypass Auto Delete** is never deleted here, but can still be approved automatically. #### Repeater Inactive After (Days) -**Default: 30. Always on. Non-destructive.** - -Days without an advert before a repeater is marked **Inactive** and hidden from the map. This applies to **Active** repeaters and to **Excluded** ones (repeaters parked by an ID collision). +**Default: 30. Always on. Doesn't delete anything.** -Nothing is lost — the record, its notes, its history, and its leaderboard contributions all stay. It returns to Active by itself the next time an advert gets through. +Days without an advert before an **Active** or **Ambiguous** repeater is marked **Inactive** and hidden from the map. -Ageing out Excluded repeaters is what unsticks a stale collision: while a colliding repeater is still Excluded it keeps its partner excluded too, and once it goes Inactive it drops out of that comparison and the partner returns to Active on its next advert. See [Duplicate Repeater IDs](https://wiki.meshmapper.net/duplicaterepeaterid/). +Nothing is lost: the record, notes, history and leaderboard points all stay. It goes back to Active on its own at its next advert. -Configurable per region (previously fixed at 30 days). +This is also what clears an old collision. Once an Ambiguous repeater goes Inactive, it's left out of the ID check, and its partner goes back to Active at its next advert. See [Duplicate Repeater IDs](duplicaterepeaterid.md). !!! example - Raise it to **60** for a repeater whose adverts only occasionally reach an observer, giving it two months to land one. Lower it to **14** for a dense region that wants stale entries off the map quickly. + Raise it to **60** for a repeater whose adverts only sometimes reach an observer. Lower it to **14** in a busy region that wants old entries off the map quickly. -!!! warning "This won't help a repeater with no observer coverage" - Raising the value only helps if adverts get through *sometimes*. If no observer can hear the repeater at all it ages out regardless, and its wardrive pings won't stop that. That's an observer gap, not a timer problem. (**Single Observer Mode** disables this ageing entirely.) - -!!! tip "Per-repeater override" - **Bypass Auto Delete** on a repeater (Repeaters tab) exempts it from every routine in this section. Use it for seasonal or knowingly-offline deployments you want to keep on the map. +!!! warning "This won't help a repeater no observer can hear" + A higher value only helps if adverts get through *sometimes*. If no observer hears the repeater at all, it ages out anyway, and its wardrive pings won't stop that. The fix is an observer, not a timer. (**Single Observer Mode** turns this ageing off.) #### Repeater Retention / Auto-Delete (Days) -**Default: blank (Disabled). Opt-in. DESTRUCTIVE.** +**Default: blank (off). DELETES DATA.** !!! danger "This permanently deletes repeaters" - An Inactive repeater that hasn't adverted for this many days is **permanently deleted**. There is no undo. **Leave it blank to keep it off** — that's the default. + An Inactive repeater that hasn't adverted for this many days is **permanently deleted**. There is no undo. **Leave it blank to keep it off.** - A repeater with no observer in range looks identical to a dead one here. Enabling this in a region with patchy observer coverage will delete repeaters that are still transmitting. + A repeater no observer can hear looks the same as a dead one. Turning this on in a region with patchy observer coverage will delete repeaters that are still working. -Whether to use it is each region's call. Some accumulate dead records — test devices, replaced hardware — and want the database pruned without doing it by hand. +Some regions collect dead records (test devices, replaced hardware) and want them pruned without doing it by hand. -**The clock runs from the last advert**, not from the day the repeater went Inactive, so the two windows overlap. +**The clock runs from the last advert**, not from when the repeater went Inactive. !!! example Inactive After = **30**, Retention = **90**. A repeater last adverts January 1st: - - **January 31st** — marked Inactive, hidden from the map. Record intact. - - **April 1st** — permanently deleted. + - **January 31st:** marked Inactive and hidden. Record kept. + - **April 1st:** permanently deleted. - So it sat Inactive, still on file, for 60 days — not 90. Set both to 30 and it's marked Inactive and deleted on the same night. + So it sat Inactive for 60 days, not 90. Set both to 30 and it's marked Inactive and deleted on the same night. -**Minimum:** your **Repeater Inactive After** value, or 7 days, whichever is larger — a repeater can't be deleted before it's marked Inactive. The minimum shown next to the field updates as you type. **A smaller value is rejected outright and auto-delete stays off.** It is not rounded up. +**Minimum:** your **Repeater Inactive After** value or 7 days, whichever is larger. A smaller value is rejected and auto-delete stays off. -Leaderboard points and Explorer credit survive; only the repeater record goes. Deletions are written to the audit log. +Leaderboard points and Explorer credit are kept; only the repeater record goes. Deletions are written to the History log. -Nothing is deleted until the MeshMapper operator enables the purge fleet-wide — setting a value alone isn't enough. +Nothing is deleted until MeshMapper enables the purge for everyone. Setting a value alone isn't enough. #### Ghost Retention (Days) **Default: 30. Always on.** -A **ghost** is a device that has only ever been heard passively — it answered a wardriver's discovery ping but never sent an advert. With no advert it has no name and no fixed location, so it never appears on the map. Ghosts are kept in a separate catalog as evidence that *something* with that ID is transmitting nearby. +A **ghost** is a device that has only been heard answering a wardriver's discovery ping and has never sent an advert. With no advert it has no name and no fixed location, so it never shows on the map. Ghosts are kept in a separate list as evidence that *something* with that ID is transmitting nearby. -This setting drops a ghost after this many days without being heard. +A ghost is dropped after this many days without being heard. Once MeshMapper gets an advert from it, it becomes a normal repeater straight away and the rules above apply. -A ghost stops being a ghost the moment MeshMapper receives an advert from it — it becomes a normal repeater straight away, and every rule in [Repeater Lifecycle & Cleanup](#repeater-lifecycle-cleanup) applies to it from then on. Ghost Retention only governs devices that have never adverted. +The ghost list is what makes [Pending Repeater Links](#pending-repeater-links) work: a local ghost sharing a distant repeater's ID shows the pings belong to the local device. Set it too low and you lose that evidence. -That catalog is what makes [Pending Repeater Links](#pending-repeater-links) work — a local ghost sharing a distant repeater's ID is the evidence that the pings belong to the local device. Set it too low and you lose that evidence. +!!! info + Ghost cleanup only touches the ghost list. It never changes or deletes a registered repeater. -!!! example - An unregistered repeater `C4A8…` answers discovery 40 times but never adverts. It's logged as a ghost and used as evidence for any pending-link decision on that ID. If nobody hears it for 30 days, the ghost is dropped. If its owner fixes it and it starts adverting, it becomes a normal repeater on the spot — name, location, and the standard timers. +#### CARpeater Retention (Days) -!!! info - Ghost cleanup only touches the ghost catalog — it can never delete or modify a registered repeater. +**Default: 90.** A [CARpeater](#carpeaters) tag that hasn't been reported for this many days is removed. #### New Repeaters Enter Pending State -When enabled, newly discovered repeaters will enter a **Pending** state instead of **Active**. Pending repeaters are hidden from the map until an admin reviews and approves them, and are resolved automatically once they have been in the queue for 3× the stale timer — see [Pending repeater resolution](#pending-repeater-resolution) for exactly how that decision is made. In multiregion mode, this setting is configured per-region under Region-Specific Settings. +When on, newly found repeaters start as **Pending** instead of **Active**. They stay off the map until an admin approves them, or until they're sorted out automatically (see [Pending repeater resolution](#pending-repeater-resolution)). -!!! warning "Data Inaccuracy Warning" - Pings are not associated to a repeater until it has been approved and set to **Active**. Any coverage heard while it sits Pending stays unlinked, and approving it later does not backfill those pings — use **Reassociate Repeater** in the Tools tab if you need them attached. +!!! warning "Pending repeaters don't collect coverage" + Pings aren't linked to a repeater while it's Pending, and approving it later doesn't fill them in. Use **Reassociate Repeater** in the Tools tab if you need them linked. #### Disable Duplicate ID Detection Logic -Allows the region to opt-out of MeshMapper's strict duplicate ID collision handling. When enabled, repeaters with colliding IDs will remain active, and pings will associate with all matching repeaters. +Turns off MeshMapper's duplicate ID handling. Colliding repeaters stay Active, and pings link to every matching repeater. - - *Warning:* This compromises data accuracy. A warning badge will be displayed on the public map, and the region will be excluded from global leaderboards. - - [Learn more about overriding duplicate detection](https://wiki.meshmapper.net/overrideduplicates/) + - *Warning:* This hurts data accuracy. The public map shows a warning badge, and the region is left out of global leaderboards. + - [Learn more about overriding duplicate detection](overrideduplicates.md) -### Coverage Ping Settings +#### Coverage Ping Settings -These control how coverage pings are linked to repeaters and when orphaned pings are removed. They are independent of the repeater timers above. +These decide how coverage pings are linked to repeaters and when orphaned pings are removed. -#### Pending Link Distance (km) +##### Pending Link Distance (km) -**Default: 200. 0 disables. Affects new pings only.** +**Default: 200. 0 turns it off. Only affects new pings.** -A ping matching a repeater more than this far away is not linked automatically — it's held as a **Pending Repeater Link** in the Alerts tab for an admin to approve. The pings stay on the map, just not tied to a repeater until you decide. +A ping that matches a repeater farther away than this isn't linked automatically. It's held as a **Pending Repeater Link** in the Alerts tab for you to decide. The pings stay on the map, just not linked to a repeater. -This catches an unregistered local repeater sharing a short ID with a registered one far away, which would otherwise draw coverage lines across the country. +This catches an unregistered local repeater that shares a short ID with a registered one far away, which would otherwise draw coverage lines across the country. !!! question "Why 200?" - LoRa long-hauls at this distance are unlikely. A handheld hearing a repeater that far away almost always means an unregistered local device with the same short ID. - -Lower it in a compact region to catch more collisions at the cost of more alerts; raise it if you genuinely have extreme long-haul links. **0** disables the check and always auto-links. - -See [Pending Repeater Links](#pending-repeater-links) for how to resolve the alerts. + LoRa links this long are unlikely. A handheld hearing a repeater that far away almost always means an unregistered local device with the same short ID. -#### Stale Ping Cleanup (Auto-Delete Orphaned Pings) +Lower it in a small region to catch more collisions (and get more alerts). Raise it if you really have very long links. **0** always links automatically. -To clear coverage left behind by a repeater that moved or was removed, first review the **Stale Ping Cleanup** preview. Save a retention window for automatic cleanup, or use **Backfill Purge Now** for eligible old orphaned pings after reviewing its count. The purge is permanent; do not use it merely to hide a repeater from the map. +See [Pending Repeater Links](#pending-repeater-links) for how to handle the alerts. -**Default: Disabled. Options: Disabled / 30 / 60 / 90 days. DESTRUCTIVE.** +##### Stale Ping Cleanup (Auto-Delete Orphaned Pings) -Ages out **orphaned** pings — ones whose repeater has moved more than 100 m away or vanished entirely. These are the pings the map already shows as **"(Gone)"**. A ping only counts as orphaned when *every* repeater on it is gone; anything still resolving is kept. +**Default: Disabled. Options: Disabled / 30 / 60 / 90 days. DELETES DATA.** -##### The grace clock +Removes **orphaned** pings: pings whose repeater has moved more than 100 m or is gone. The map already shows these as **"(Gone)"**. A ping only counts as orphaned when *every* repeater on it is gone. Don't use this just to hide a repeater from the map. -**Choosing a window does not delete your existing backlog.** This is the part people misread. - -The nightly job starts a clock the first night it sees a ping orphaned, and only deletes it once it has stayed orphaned for the full window. If the repeater comes back within 100 m, the clock clears and the ping is kept. +**Picking a window doesn't delete your existing backlog.** The nightly job starts a clock the first night it sees a ping orphaned, and only deletes it once it has stayed orphaned for the full window. If the repeater comes back within 100 m, the clock clears and the ping is kept. !!! example You pick **30 days** on June 1st, and you have pings orphaned since last year. - - **June 1st** — they're flagged and the clock starts. Nothing is deleted. - - **July 1st** — 30 days orphaned. *Now* they're deleted. - - A repeater returning on June 20th resets the clock and its pings are kept — unless it comes back more than 100 m from where it was. + - **June 1st:** they're flagged and the clock starts. Nothing is deleted. + - **July 1st:** 30 days orphaned. *Now* they're deleted. -Leaderboard points and Explorer credit are preserved; only the ping record is removed. + If a repeater comes back on June 20th (within 100 m), its pings are kept. -##### Backfill Purge Now… +Leaderboard points and Explorer credit are kept; only the ping record is removed. -The immediate alternative — it doesn't wait out the clock. It deletes every ping that is **already** orphaned **and** older than your saved window, plus any no-location (0,0) pings of any age. Anything orphaned more recently than the window is kept, so a briefly-offline repeater doesn't lose data. +**Backfill Purge Now…** clears the backlog right away instead of waiting. It deletes every ping that is **already** orphaned **and** older than your saved window, plus any no-location (0,0) pings of any age. - 1. Save a window (30 / 60 / 90) first — the preview won't run without one. - 2. Click **Backfill Purge Now…** to open a read-only preview. - 3. Review what would go: totals, a breakdown by repeater with the reason each qualifies, and one by date. Multi-region groups also get a per-region breakdown. + 1. Save a window (30, 60 or 90) first. The preview won't run without one. + 2. Click **Backfill Purge Now…** to open a preview. Nothing is deleted yet. + 3. Check what would go: totals, what share of the region's pings that is, and breakdowns by repeater and by date (and by region for groups). The preview confirms leaderboard and Explorer credit are kept. 4. Confirm the exact ping count. !!! example Window = 30 days, run on June 1st: - - January ping, orphaned → **deleted**. - - May 25th ping, orphaned → **kept** (inside the window; the repeater may only be briefly offline). - - March ping at 0,0 → **deleted** (no-location pings go at any age). - - January ping whose repeater is still live nearby → **kept** (not orphaned). - -Use it to clear a backlog now instead of waiting for each ping to age out. + - January ping, orphaned: **deleted**. + - May 25th ping, orphaned: **kept** (inside the window; the repeater may only be briefly offline). + - March ping at 0,0: **deleted** (no-location pings go at any age). + - January ping whose repeater is still nearby: **kept** (not orphaned). !!! info - The nightly sweep won't run with a window under 30 days, which is why there's no shorter option. And like the repeater purge, real deletion is blocked until the MeshMapper operator enables it fleet-wide — until then both the nightly job and this button only *mark* pings, and the preview will tell you so. + There's no window under 30 days. And like the repeater purge, nothing is actually deleted until MeshMapper enables it for everyone; until then pings are only marked, and the preview tells you so. -With the **Ping Purge Cleanup Report** notification on, you'll get a Discord DM summarising what was removed (one combined message per group). +With the **Ping Purge Cleanup Report** notification on, you get a Discord DM summarising what was removed (one message per group). -### Multi-region groups +### Wardriving -The cleanup settings above are split between the group and its member regions. +#### Radio Channels -**Group-wide** (Multi-Region Settings → Group Defaults): +Wardriving rules are set per radio channel, one row each. The **\*** row covers every radio that doesn't have its own row. Click **Add preset** to add a row for a channel; a new row starts with Flood Off and Slots 0. - - Stale Repeater Age - - Pending Link Distance - - Stale Ping Cleanup — including Backfill Purge, which runs across every member region +| Column | What it does | +| --- | --- | +| **Slots** | How many people can transmit on that channel at once. **0** makes it listen-only. | +| **Flood** | **Off** turns off Active and Hybrid modes, so wardrivers can only listen. Forces Slots to 0. | +| **Path B** | App Path Bytes: **Device**, **2** or **3**. Tells the app what path width to set. It doesn't change repeaters. See [Multi-Byte Repeaters](multibyte.md). | +| **Hybrid** | Forces Hybrid mode (turns off Active mode). Try it if your mesh drops packets from heavy traffic. | +| **DISC drop** | When on, Discovery pings that get no reply show as DROP (red). When off, they don't show. | +| **Interval** | Shortest time between pings: 15s, 30s or 60s (default 60s). | +| **Smart** | Locks the app's Smart Pinging on, so pings are held in squares that already have a recent result. | +| **Window** | How recent a result must be for Smart Pinging: 1, 3, 7, 14 or 30 days (default 14). | +| **Scopes** | Scope discovery: after each discovery, the app asks each repeater it found which scopes it carries. Adds a little extra traffic. Off by default. | +| **Re-check** | How many days a repeater's scope answer counts as fresh before it's asked again (minimum 7, default 14). | -**Per region**, on each member's own settings: +#### Other wardriving settings - - Repeater Inactive After - - Repeater Retention / Auto-Delete - - Ghost Retention + - **Public Channels:** Channels the app listens on for passive coverage. **#public** is always included; add any other # channels you know of. + - **Wardriving Scope:** The scope the app puts on every Active and Hybrid ping. Repeaters not set up for it drop those pings. If you don't use scopes, leave it at **\***. + - **Disable Detailed Statistics (Hide Detail):** *(Groups only)* Hides the Repeater Coverage, Neighbours, Scopes and Backbone layers on the map. -Open a member region and the group-controlled fields are greyed out — the group's value wins, so change them from the group panel. Where a group hasn't set a value, the region's own applies; if neither has, the default does. +### MQTT Brokers & Observers -### Region Boundary +Called **Group MQTT Brokers** on a group panel. -The **Region Boundary** section allows you to view and edit the geographic boundary of your region. + - **Observers:** The observers your region takes data from. Paste each observer's full 64-character Public ID. + - **Subscribe to all local observers:** When on, your region uses packets from any observer connected in its area. When off, only the observers you list are used. Turn it off if a far-away observer is being counted as part of your mesh. + - **Add Broker:** Adds your own MQTT broker: Display Name, Username, Password, Badge Icon, Badge Color, Hosts and Enabled. Each broker can be tested, edited, paused or deleted. **Last data ingested** shows how fresh its data is, and the **Connection log** helps with problems. A broker must run meshcore-mqtt-broker in WebSocket mode with SSL (`wss://`) and have a role 2 subscriber account. - - **Draw Polygon**: Use the **Polygon Tool** to draw or redraw the region boundary directly on the map. - - **Import GeoJSON**: Click the **Import GeoJSON** button to paste GeoJSON data from an external source (e.g., [geojson.io](https://geojson.io)). Supported formats include `Polygon`, `MultiPolygon`, `Feature`, and `FeatureCollection`. - - **Center Pin**: The center pin automatically moves to the center of the polygon when one is drawn or imported. You can also drag it manually. This determines where the region appears on the global map. - - **Lat / Lon / Radius**: The latitude, longitude, and radius fields are used as a fallback if no polygon is defined. If a polygon is drawn, it takes precedence over the radius. - - **Auto Generate Boundry**: Use this option to have AI attempt to draw your regions boundry for you. +Most regions don't need their own broker. Point observers at the [MeshMapper MQTT broker](mqtt-main.md). -## User Settings +### Data Sources -The **User Settings** tab allows administrators to manage their own account. + - **Single Observer Mode (Prevent Stale Repeaters):** Turn this on if your region has only one observer. The nightly cleanup then skips your region's repeaters completely: they're never marked stale, never marked Inactive and never deleted. Ghost cleanup still runs. - - **Change Key**: Update your admin login key. - - **Contact Info**: Update your contact information (e.g., Discord handle, email). This is displayed to all users. - - **API Access**: Generate or manage your Coverage API key. Each admin is allowed one key per region with a fixed rate limit of 100 requests per day. A description/reason is required when generating a key. Use **Regenerate** to replace an existing key (the old key stops working immediately). See [Coverage API](coverage-api.md) for usage details. +### Notifications (Webhooks) -## Alerts & History +Sends alerts to a **webhook** (Slack, Home Assistant, your own automation, and so on). - - **Alerts**: Automatically detects configuration issues, including: - - **Repeater Clock Alerts**: Repeaters whose embedded timestamp differs from the server time by more than 120 seconds. An incorrect clock can affect packet routing and deduplication. - - **Duplicate Repeater IDs** (Collisions): Multiple repeaters sharing the same short public ID. - - **Pending Repeaters**: Repeaters awaiting approval (when "New Repeaters Enter Pending State" is enabled). - - **Pending Repeater Links**: Pings held for review because the repeater they resolve to is implausibly far away — see below. - - **Suspicious Live Sessions**: Sessions containing pings whose implied speed between consecutive fixes exceeds the flyover threshold — typically a device that was flown, or otherwise moved faster than any ground vehicle. Each row shows who, session ID, start time, peak speed, and ping count. You can **delete** the session to scrub the pings, or **dismiss** it if the movement was legitimately fast (a train, for example). Dismissed sessions are kept in a collapsed list so the decision is reviewable. - - **History**: An audit log of all administrative actions (who edited what and when), ensuring accountability. + - **Webhook URL:** The HTTPS address to send to. Click **Send Test** to check it. + - **Events to send:** Ambiguous Repeater ID, Pending Repeater, Offline Observer, Visitor Message, Suspicious Flight and Pending Repeater Link. -### Pending Repeater Links +The webhook turns itself off after 3 permanent failures. See [Webhooks](webhooks.md). -Generated by the [Pending Link Distance](#pending-link-distance-km) setting: a ping's repeater ID resolved to exactly one registered repeater, but it sits farther away than your configured distance. +### Region Boundary -The pings **stay on the map** — they're just not tied to a repeater until you decide. Nothing is deleted or hidden. +Where your region is and what counts as inside it. See [Defining a Region's Boundary](region_boundaries.md) for a step-by-step guide. -#### Reading the evidence + - **Center of Region:** A pin you can drag. + - **Country:** The two-letter country code. + - **Region Radius:** Worked out from the boundary. You can't edit it. + - **Auto Boundary:** Loads real borders from OpenStreetMap (or geoBoundaries). Drag the pin, pick **State/Prov**, **County** or **Local**, click the areas you want, then click **Use selected**. + - **Draw Boundary** (under Advanced Mapping): Draw or edit the boundary by hand. + - **Import GeoJSON:** Paste a `Polygon`, `MultiPolygon`, `Feature` or `FeatureCollection`. Only use custom GeoJSON in special cases. + - **Export GeoJSON:** Downloads the current boundary. Do this before a big change. -Each row gives you what you need to decide: +### Multi-region groups - - **The resolved repeater** — ID, name, region, and distance. - - **What was actually heard on-air** — the short token the radio really reported. It's often shorter than the resolved ID, and that's the crux: the extra bytes came from MeshMapper's resolution, not from the radio. - - **Nearby ghosts** — unregistered devices answering discovery in the area. **Strong matches** start with the exact token that was heard; if one exists, the pings almost certainly belong to it and the panel says so. **Weak matches** share only the first byte and are de-emphasised. - - **The held pings** — date, session, heard token, coordinates, and a **🗺️ Map** link to that exact ping. +A group panel splits settings between the group and its member regions. -#### Your three choices +**Group Defaults** (apply to every member region): + + - Stale Repeater Age + - Pending Link Distance + - Neighbour links + - Scopes to Monitor + - Mesh Scopes retention + - Stale Ping Cleanup, including Backfill Purge across every member region + - Disable Detailed Statistics + - Disable Duplicate ID Detection Logic - - **Link to repeater** — you know that repeater genuinely reaches this area. The pings link to its current position, and future far pings for this ID link automatically. - - **Leave unlinked** — the likely case. Pings stay on the map, marked as tied to no repeater. New far pings will alert again. - - **Leave unlinked + suppress** — same, but future far pings are held quietly with no new alert. Use it once you've confirmed there's a local unregistered device. +The group panel also has **Wardriving → Radio Channels** (Slots are totals for the whole group), **Public Display** and **Group MQTT Brokers**. -With more than one row you also get **Suppress all**. Suppressed IDs sit in their own list with held-ping counts and can be restored individually or all at once. +**Per region**, in each member region's card on the group panel: -!!! info "Suppression clears itself" - MeshMapper watches the situation around each ID. If a local repeater with that ID registers, the distant one moves or is deleted, or a new ghost appears, suppression clears and you're alerted again. Same for a confirmed link. + - New Repeaters Enter Pending State + - Public Channels + - Wardriving Scope + - Single Observer Mode + - MQTT Observers and Subscribe to all local observers + - Webhook settings + - Region Boundary -!!! warning "When linking is refused" - - **Unplaced repeater** — it has no usable position, so linking would bake the pings to a meaningless location. Place it on the map first. - - **Newly ambiguous** — more than one repeater now matches that ID, so linking would be a guess. Review that ID's repeaters first. +On a member region's own panel you'll see *"This region is part of a multiregion group. Some settings cannot be edited here."* **Repeater Inactive After**, **Repeater Retention**, **Ghost Retention** and **CARpeater Retention** are read-only in a group; ask MeshMapper staff to change them. + +## User Settings + +### My Account + +Your MeshMapper account: the same login for the [portal](portal.md) and every admin panel. + + - **Username** and **Email** (shows whether it's verified). + - **Change password**, or **Set password** if you don't have one yet. If you sign in with Discord, you can **Remove password**. + - **Link Discord** / **Unlink Discord**. + - **Contact info:** Shown to other admins in the Administrators tab and to visitors in the map's **Region Info**. -Admins with the **Pending Repeater Link** notification on get a daily reminder. Each ID notifies once, resetting if its situation changes. +### Notifications -## Notifications +Discord DMs from the MeshMapper bot, with one set of boxes per region. You need Discord linked to your account. -Link your Discord to MeshMapper to receive DM's from the MeshMapper bot. + - **Ambiguous Repeater ID:** A repeater's ID collides with another's, making them Ambiguous. See [Duplicate Repeater IDs](duplicaterepeaterid.md). + - **Pending Repeater:** A daily reminder when your region has repeaters waiting for approval. Only useful when **New Repeaters Enter Pending State** is on. + - **Messages From Visitors:** Lets map visitors message you from your region's **Region Info**. + - **Offline Observer:** Once a day, MeshMapper checks each observer that sent data in the last 7 days. If it hasn't sent anything within your **Stale Repeater Age**, you get an alert. + - **Suspicious Flight:** A live session has pings moving faster than any ground vehicle. Matches **Suspicious Live Sessions** in the Alerts tab. + - **Pending Repeater Link:** A daily summary of repeater IDs whose pings are held for review. Each ID notifies once, and again only if its situation changes. See [Pending Repeater Links](#pending-repeater-links). + - **Ping Purge Cleanup Report:** What [Stale Ping Cleanup](#stale-ping-cleanup-auto-delete-orphaned-pings) removed, broken down by date and repeater. Groups get one combined message. Only sent when something was deleted. DM only; there's no webhook for it. - - **Alert on Duplicate Repeater ID**: Notifies you when a repeater has sent an advert, but its ID collides with another, putting both repeaters into Excluded status. [See Duplicate Repeater ID](https://wiki.meshmapper.net/duplicaterepeaterid) - - **Alert on Pending Repeater**: Once a day, receive a notification if your region has repeaters in **Pending** state that are awaiting review. This notification is only relevant if "New Repeaters Enter Pending State" is enabled for the region. - - **Allow Messages From Visitors**: When enabled, a map visitor can send a message to you directly from the "Region Info" page of your regions map. - - **Alert on Offline Observer**: Once a day (around 0800 EST/EDT) MeshMapper will review all data received via your regions MQTT observers (pings, repeater adverts, companion adverts) for the past 7 days. If a particular observer has sent data within that time, but not within the "Stale Repeater Age" time configured for your region, then this observer is potentially offline. Receive an alert when this is the case. - - **Suspicious Flight**: Alerts you when a live session contains pings implying a speed faster than any ground vehicle — usually a device that was flown. Corresponds to the **Suspicious Live Sessions** alert. - - **Pending Repeater Link**: Once a day, a summary of repeater IDs whose pings are held for review because they resolved to an implausibly distant repeater. Each ID notifies once, and again only if its situation changes. See [Pending Repeater Links](#pending-repeater-links). - - **Ping Purge Cleanup Report**: A summary of what [Stale Ping Cleanup](#stale-ping-cleanup-auto-delete-orphaned-pings) removed — ping count, plus a breakdown by date and repeater. Multiregion groups get one combined message. Only sent when something was actually deleted. +The other events can also go to a webhook; see [Notifications in Settings](#notifications-webhooks). -These events are also available as **webhook** subscriptions, configured separately in the Settings tab. See [Webhooks](https://wiki.meshmapper.net/webhooks/). +### API Access -Webhooks can also be configured per-region to send these same notifications to any HTTPS endpoint (Slack, Home Assistant, custom automation, etc.). See [Webhooks](https://wiki.meshmapper.net/webhooks) for setup instructions. +Create a key for the [Coverage API](coverage-api.md). Each admin gets one key per region, limited to 100 requests a day (usage shows as "n / 100"). A description is required. **Regenerate API key** replaces your key; the old one stops working straight away. diff --git a/docs/app_connection_guide.md b/docs/app_connection_guide.md index ceae901..68fa995 100644 --- a/docs/app_connection_guide.md +++ b/docs/app_connection_guide.md @@ -10,18 +10,33 @@ The Connect tab has a selector for **how** to connect to your radio: | Method | Platforms | Notes | |--------|-----------|-------| -| **BLE** (Bluetooth) | Android, iOS, Web (Chrome/Edge) | The standard method. Scan and tap your device. | -| **TCP** | Android, iOS | Connect to a network-attached radio by host and port (default 5000) — e.g., a WiFi-connected companion or a serial-to-TCP bridge. Saved connections are remembered. | -| **USB Serial** | Android (USB OTG), Web (Chrome/Edge) | Direct cable connection. Not available on iOS. | +| **BLE** (Bluetooth) | Android, iOS | The standard method. Scan and tap your device. | +| **TCP** | Android, iOS | Connect to a network-attached radio by host and port (default 5000), e.g. a WiFi-connected companion or a serial-to-TCP bridge. Saved connections are remembered. | +| **USB** (serial) | Android (USB OTG) | Direct cable connection. Not available on iOS. | -Everything below the transport (the connection workflow, sessions, zones, reconnection) works the same regardless of which method you use. +Everything below the transport (the connection workflow, sessions, zones) works the same regardless of which method you use. Automatic reconnection is the exception: it covers BLE and TCP only. + +--- + +## Before You Connect + +Before it lets you connect, the app checks your location with MeshMapper. The zone status at the top of the Connect tab shows the result: + +- **Zone name**: you are inside a region and can connect +- **Checking Zone...**: the check is still running +- **Outside Zone**: you are not inside any region. The Connect tab shows **Region Not Available** with the nearest zone and its distance, and a **Request Region Onboarding** button. +- **Maintenance**: MeshMapper is down for maintenance. You can still wardrive with **Enable Offline Mode**. +- **No Internet**, **Clock Out of Sync** or **GPS Unavailable**: the check could not finish. See [Zone Authentication](#zone-authentication). +- **Airborne**: you appear to be in an aircraft. Wardriving from an aircraft is not allowed, and you can connect again once you are back on the ground. + +[Offline Mode](#offline-mode) skips the zone and maintenance checks, but never the airborne block. --- ## Scanning for Devices 1. Open the **Connect** tab (Bluetooth icon in the bottom bar) -2. Tap **"Scan for Devices"** to start a BLE scan +2. Tap **Scan** to start a BLE scan. Before any results, the list reads "Tap Scan to search for MeshCore devices". 3. Nearby MeshCore devices appear in a list showing their name and signal strength 4. Tap your device to begin connecting @@ -29,17 +44,18 @@ Everything below the transport (the connection workflow, sessions, zones, reconn - **Android**: May need to grant Bluetooth and Location permissions - **iOS**: System will prompt for Bluetooth access -- **Web**: Chrome shows its native Bluetooth pairing dialog --- ## Remembered Devices -After your first successful connection, MeshMapper remembers that device. On future launches: +After your first successful connection, MeshMapper remembers that device. For a BLE device, on future launches: -- Your last device appears at the top of the Connect tab under "Last Connected Device" -- Tap it to reconnect without scanning -- To connect to a different device, just run a new scan +- Instead of an empty list, the Connect tab shows **Last Connected Device** with your device's name +- Tap **Reconnect** to connect without scanning. If you can't connect yet, the button reads **Outside Zone**, **Checking Zone...** or **Maintenance** instead. +- Tap **Scan** to look for a different device, or **Forget** to clear the remembered one + +TCP connections are listed under **Saved Connections** on the TCP tab. --- @@ -49,37 +65,45 @@ When you tap a device, MeshMapper runs through nine steps automatically. You can | Step | What Happens | |------|-------------| -| 1 Transport Connect | Establishes the raw connection (BLE GATT, TCP socket, or USB serial port) | -| 2 Protocol Handshake | Verifies app and firmware compatibility | -| 3 Device Info | Retrieves manufacturer string and public key (required for API auth). If this fails, the entire connection fails. | -| 4 Device Identification | Determines your device model and TX power level for reporting. Does NOT change your radio's actual power settings. | +| 1 Transport Connect | Establishes the raw connection (BLE, TCP socket, or USB serial port) | +| 2 Protocol Handshake | A short pause while the radio gets ready | +| 3 Device Info | Sends the app's protocol version and reads the firmware, manufacturer string and public key (required for API auth). If this fails, the entire connection fails. | +| 4 Device Identification | Determines your device model and power level for reporting. Does NOT change your radio's actual power settings. | | 5 Time Sync | Synchronizes your radio's clock with your phone | | 6 Session Acquisition | If Anonymous Mode is enabled, your device is first renamed to "Anonymous" on the mesh. Then authenticates with the MeshMapper API. Handles registration automatically if needed. Returns zone info, permissions, and regional settings. | | 7 Channel Setup | Creates the #wardriving channel on your radio (or reuses existing) | -| 8 GPS Init | Waits for a GPS lock on your phone | -| 9 Connected | Unified RX Handler starts, noise floor polling begins (every 5s), ready to wardrive | +| 8 GPS Init | A progress marker only. It does not wait for a GPS lock. | +| 9 Connected | Ready to wardrive. Noise floor is read every 5 seconds and battery every 30 seconds. | **After connection completes**, the app applies regional settings from the API response: -- **Regional channels**: Additional channels from the zone config are created on your radio +- **Regional channels**: The app also listens to any extra channels the regional admin has set up - **Flood scope**: If the regional admin has set a scope, it is applied to your radio so TX messages stay within that region -- **Regional enforcement**: Hybrid Mode, discovery drop, and minimum ping interval may be enforced by the regional admin +- **Flood traffic**: If the region allows flood traffic, the app turns **Flood Traffic** on. If the region has disabled it, Active, Hybrid and Send Ping are unavailable, and the Connect tab explains why. +- **Regional enforcement**: The regional admin may enforce Hybrid Mode, Discovery Drop, Smart Pinging (and its window), Scope Discovery (and its window), and a minimum auto-ping interval. Enforced settings are locked in Settings. +- **Regional CARpeaters**: The region's shared CARpeater list is loaded and filtered - **Path hash mode**: If the zone enforces a specific hop byte size (1/2/3-byte) and your radio differs, the app automatically reconfigures your radio to match. Restored on clean disconnect. Two dialogs may appear: - **"Multi-Byte Paths Enabled"** (info): Your radio was reconfigured to match the zone's requirement. Shows the new byte size and whether it was set by the regional admin or your own preference. - **"Firmware Update Recommended"** (warning): Your companion firmware does not support multi-byte paths. The app falls back to 1-byte mode and suggests updating to firmware v1.14.0+. +- **Account link**: If you are signed in to [My MeshMapper](portal.md) and this radio is not linked yet, the app offers to link it + +While connected, the app re-checks your zone every 60 seconds to keep slot counts fresh. + +!!! note "Antenna choice resets" + Your antenna choice (Internal or External) is cleared every time you disconnect. Select it again after each connect before you start pinging. --- ## Zone Authentication -If **Zone check failed** appears, wait for an accurate, current GPS fix and confirm that your location is inside an active MeshMapper region. The app may report a stale clock, weak GPS, a disabled region, or an unreachable server as separate errors. If your area has no region, use [onboarding](onboarding.md) rather than choosing an unrelated region code. +If the zone check fails, wait for an accurate, current GPS fix and confirm that your location is inside an active MeshMapper region. The app reports a wrong phone clock (**Phone Clock Out of Sync**), weak GPS (**Weak GPS Signal**), no internet (**No Internet Connection**) and other errors (**Zone Check Failed**) separately. It retries on its own, or offers a **Retry Zone Check** button for GPS and clock problems. If your area has no region, use [onboarding](onboarding.md) rather than choosing an unrelated region code. MeshMapper uses a zone-based authentication system. The server checks your GPS coordinates and tells you which zone you are in (if any). Each zone has a code (like "YOW" for Ottawa) and a set of rules configured by the regional admin: **Session permissions:** -- **TX Allowed**: Whether you can send channel messages. If at TX capacity, you are limited to Passive Mode only. -- **RX Allowed**: Whether passive reception is permitted +- **TX Allowed**: Whether you can send channel messages. If the zone is at TX capacity, you are limited to Passive and Trace modes. +- **RX**: Passive reception is always allowed - **TX Slots Available**: How many active wardrivers the zone can support simultaneously - **Session Expiry**: When your session expires (automatically refreshed via heartbeat) @@ -87,23 +111,32 @@ MeshMapper uses a zone-based authentication system. The server checks your GPS c - **Scope**: Flood scope for the zone. When set, your TX channel messages are scoped to that region instead of flooding the entire global mesh. Shown on the Connect tab (e.g., "#ottawa"). If no scope is set, it shows "Global." Applied automatically by setting a transport key on your radio. - **Channels**: Additional channels configured by the regional admin (e.g., regional monitoring channels) -- **Enforce Hybrid**: Whether Hybrid Mode is mandatory for the zone. When enforced, the Hybrid Mode toggle in Settings is locked. -- **Minimum TX Ping Interval**: The minimum auto-ping interval (15, 30, or 60 seconds). If set, you cannot choose a faster interval than the regional minimum. -- **Mark Failed Discovery as Drop**: When enabled, discovery requests with no response are counted as "no coverage" data and shown as DROP on the coverage map. -- **Hop Bytes**: Enforces a specific path hash size (1-byte, 2-byte, or 3-byte) for consistent data across all wardrivers in the zone. During connection, the app checks your radio's current path hash mode against the region's requirement. If they differ (e.g., your radio is set to 1-byte but the region requires 2-byte), the app automatically reconfigures your radio to match. On clean disconnect, the app restores your radio to its original setting. If your firmware does not support multi-byte paths (pre-1.14), the app will warn you that it cannot apply the regional setting. -If you are outside all zones, the status bar shows an orange dash with the name and distance to the nearest zone. +Most other rules are set **per radio preset** (frequency, bandwidth and spreading factor), so one region can have different rules for different presets: + +- **Slots**: How many wardrivers can transmit at once (default 0) +- **Disable Flood**: Turns flood traffic off for the preset (default On, so flood is off until the admin allows it) +- **Enforce Hybrid**: Makes Hybrid Mode mandatory. When enforced, the Hybrid Mode switch in Settings is locked on. Default Off. +- **Min Interval**: The minimum auto-ping interval (15, 30, or 60 seconds, default 60). You cannot choose a faster interval than the regional minimum. +- **Failed DISC as DROP**: When enabled, discovery requests with no response are counted as "no coverage" data and shown as DROP on the coverage map. +- **App Path Bytes**: Enforces a specific path hash size (device default of 1 byte, 2 bytes, or 3 bytes) for consistent data across all wardrivers in the zone. If your radio differs, the app reconfigures it at connect and restores the original setting on clean disconnect. If your firmware does not support multi-byte paths (pre-1.14), the app warns you that it cannot apply the regional setting. +- **Enforce Smart Pinging**: Locks [Smart Pinging](app_wardriving_modes.md#smart-pinging) on, with the region's window (1, 3, 7, 14 or 30 days) +- **Scope discovery**: Locks [Scope Discovery](app_settings_reference.md#scope-discovery) on, with the region's re-check window (7 days or more) + +If you are outside all zones, the zone chip in the status bar shows an orange "—". Tap it to see the name and distance of the nearest zone. + +**Leaving your zone while wardriving.** If you drive out of your zone, the app pauses wardriving and shows **Out of Zone** with the nearest zone. You get 5 minutes to come back. If you return, wardriving resumes. If not, the app disconnects. Driving straight into a neighbouring zone shows **Changing Zone...** while your session moves to the new zone. --- ## Automatic Reconnection -If your Bluetooth connection drops unexpectedly (out of range, radio restart, etc.), MeshMapper will attempt to reconnect automatically. +If your BLE or TCP connection drops unexpectedly (out of range, radio restart, etc.), MeshMapper will attempt to reconnect automatically. USB connections do not reconnect on their own. **What you see:** - "Reconnecting..." overlay on the map -- Current attempt number (up to 3 attempts) +- Current attempt number (up to 3 attempts, 3 seconds apart, or 5 seconds after an iOS pairing error) - Device name - Cancel button to stop trying @@ -114,7 +147,13 @@ If your Bluetooth connection drops unexpectedly (out of range, radio restart, et - Noise floor session - Auto-ping restarts automatically after successful reconnect -**If all 3 attempts fail:** The app falls back to a full disconnect cleanup. +**If all 3 attempts fail, or 30 seconds pass:** The app falls back to a full disconnect cleanup. + +--- + +## Idle Disconnect + +If you stay connected without sending a manual ping or starting an auto mode for **15 minutes**, the app disconnects and logs "Disconnected: 15 minutes of inactivity". --- @@ -126,16 +165,18 @@ Tap the **Disconnect** button on the Connect tab. The app performs a clean shutd 2. Ends the current noise floor session 3. Stops the background service 4. Flushes any buffered RX observations -5. Clears the API upload queue (pings won't have a valid session after disconnect) -6. Releases your session with the MeshMapper API -7. Deletes the #wardriving channel from your radio (if "Delete Channel on Disconnect" is enabled in Settings) +5. Saves your Offline Mode session, if you are offline +6. Clears the API upload queue (pings won't have a valid session after disconnect) +7. Releases your session with the MeshMapper API 8. Restores your device's original name if Anonymous Mode renamed it during connection 9. Restores your radio's original path hash mode if it was changed during connection (e.g., region required 2-byte but your radio was set to 1-byte) -10. Closes the Bluetooth connection -11. Resets all state +10. Clears the flood scope from your radio +11. Deletes the #wardriving channel from your radio (if "Delete Channel on Disconnect" is enabled in Settings) +12. Closes the connection (BLE, TCP or USB) +13. Resets all state !!! warning - Steps 7, 8, and 9 (channel deletion, name restoration, and path hash restoration) all happen while BLE is still connected because these commands need the BLE link to reach the radio. + Steps 8 to 11 (name restoration, path hash restoration, scope clearing and channel deletion) happen while the radio is still connected, because these commands need the link to reach the radio. --- @@ -145,19 +186,21 @@ If you don't have internet, or the MeshMapper API is in maintenance mode, use ** **To enable:** -- Tap the **"Go Offline"** button on the Connect tab +- Tap the **Go Offline** button on the Connect tab and confirm. This works before or while connected. +- Or tap **Enable Offline Mode** on the Connect tab when it shows no internet or maintenance **In Offline Mode:** - Zone validation is skipped (zone chip shows a grey dash) -- All ping data (TX, RX, DISC) is saved to local session files +- Send Ping, Active and Hybrid are unavailable (they need an online session). Passive and Trace modes work. +- Ping data is saved to local session files, and the app saves your progress every 60 seconds - Session files are named by date (e.g., "2026-03-20.json") - Manage sessions in **Settings > Data > Offline Sessions** **When you are back online:** 1. Open **Settings > Data > Offline Sessions** -2. Tap upload button next to each session to send to MeshMapper +2. Tap the upload button next to each session to send it to MeshMapper. Uploading needs your phone's location, but not the radio. 3. Or download session files for backup !!! warning @@ -174,7 +217,7 @@ Prefer not to broadcast your device's real name? Enable **Anonymous Mode** in Se - Cannot be toggled while auto-ping is running (stop auto-ping first) !!! warning - You must **disconnect cleanly** for your device name to be restored. If the app crashes or BLE drops unexpectedly, your radio may still advertise as "Anonymous" until you connect and disconnect again cleanly. + You must **disconnect cleanly** for your device name to be restored. If the app crashes or the connection drops unexpectedly, your radio may still advertise as "Anonymous" until you connect and disconnect again cleanly. --- @@ -182,6 +225,7 @@ Prefer not to broadcast your device's real name? Enable **Anonymous Mode** in Se During long wardriving sessions, MeshMapper automatically sends heartbeat requests to keep your session alive: +- Turned on when you connect online - Fires about 1 minute before session expiry - Server responds with a new expiration time - Happens transparently in the background @@ -190,14 +234,13 @@ During long wardriving sessions, MeshMapper automatically sends heartbeat reques ## Background Operation -When you start auto-ping, MeshMapper enables background operation to keep Bluetooth and GPS alive: +When you start auto-ping, MeshMapper enables background operation to keep the radio connection and GPS alive: -- **Android**: Persistent foreground notification showing the current mode and live stats. No sound or vibration. +- **Android**: Persistent foreground notification titled "MeshMapper - *Mode* Mode" (for example "MeshMapper - Hybrid Mode") with live stats. No sound or vibration. - Active / Hybrid: `TX: N | RX: M | Queue: P` - Passive: `RX: M | Queue: P` - Trace: `Trace: N | RX: M | Queue: P` - **iOS**: Uses declared background modes (bluetooth-central, location). For best results, enable "Background Location" in Settings to upgrade to "Always" location permission, which prevents iOS from throttling during extended sessions. -- **Web**: Not available. Browser tab must remain active for Web Bluetooth. !!! warning "Android screen-off wardriving" Some Android phones may pause wardriving when the screen is off. If this happens, open **Android Settings > Apps > MeshMapper > App battery usage** and select **Unrestricted**. This may increase battery use. diff --git a/docs/app_getting_started.md b/docs/app_getting_started.md index c5b8f57..13eb6fb 100644 --- a/docs/app_getting_started.md +++ b/docs/app_getting_started.md @@ -1,6 +1,6 @@ # Getting Started -Welcome to MeshMapper, a community-driven wardriving app for MeshCore mesh network devices. MeshMapper lets you connect to a MeshCore radio over Bluetooth, send GPS-tagged pings across the mesh, and contribute coverage data to the [MeshMapper community map](https://meshmapper.net/). +Welcome to MeshMapper, a community-driven wardriving app for MeshCore mesh network devices. MeshMapper connects to your MeshCore radio, sends pings across the mesh, and adds what it hears to the [MeshMapper community map](https://meshmapper.net/). Your location goes only to the MeshMapper server; by default, pings on the air carry an anonymous token, not your coordinates. --- @@ -8,9 +8,9 @@ Welcome to MeshMapper, a community-driven wardriving app for MeshCore mesh netwo 1. **A MeshCore-compatible radio device** — Any device that supports MeshCore will work with MeshMapper. It is recommended to run up-to-date firmware on your device, as some features require v1.14.0 or newer. -2. **A phone or computer** — Android, iOS, or a Chromium-based browser (Chrome or Edge) -3. **GPS/location services** enabled on your device -4. **Bluetooth** enabled on your device +2. **An Android or iOS phone** +3. **GPS/location services** enabled on your phone +4. **Bluetooth** enabled on your phone (or use TCP or USB instead, see below) --- @@ -24,38 +24,40 @@ Welcome to MeshMapper, a community-driven wardriving app for MeshCore mesh netwo **Beta releases:** -In the MeshMapper Discord server, open **Channels & Roles** and select **Yes** for beta testing. Then choose your platform: +To hear about betas, join the MeshMapper Discord server, open **Channels & Roles**, and opt in to beta testing. Then choose your platform: - **iOS:** [Join the beta in TestFlight](https://testflight.apple.com/join/PXxfr5Jr). - **Android:** [Download the beta APK from GitHub](https://github.com/MeshMapper/MeshMapper_Project/releases/), or [add MeshMapper to Obtainium](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22net.meshmapper.app%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2FMeshMapper%2FMeshMapper_Project%22%2C%22author%22%3A%22MeshMapper%22%2C%22name%22%3A%22MeshMapper%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Atrue%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%7D%22%2C%22overrideSource%22%3A%22GitHub%22%7D) to follow prereleases. -**Web (Chrome/Edge only):** - -- [wd.meshmapper.net](https://wd.meshmapper.net) -- Requires Chrome or Edge (Safari is not supported, it lacks the Web Bluetooth API) - -!!! note - The web app is experimental and has not been widely tested. It should be technically stable, but the mobile apps are the recommended experience. - --- ## First Launch -When you first open MeshMapper, you will see a **location disclosure dialog** explaining why the app needs GPS access. This dialog explains that MeshMapper collects your location to: +When you first open MeshMapper, you will see a **Location Access Required** dialog explaining why the app needs GPS access. It says MeshMapper collects your location to: - Track where you send pings on the mesh network - Map coverage areas for the community - Record which repeaters hear your device -It also discloses that your location data is uploaded to the MeshMapper API and displayed on public coverage maps at meshmapper.net. If you prefer to be more anonymous, enable the Anonymous Mode feature in Settings, or wardrive in Offline Mode and never upload your sessions. +It also explains that your location data is uploaded to the MeshMapper API and used for the public coverage maps at meshmapper.net, and that Offline Mode stores data on your phone without uploading it. !!! info "What is a 'ping'?" Throughout MeshMapper, "ping" refers to any packet the app sends out on the mesh. This includes channel messages (TX), discovery requests (DISC), and trace requests (TRC). Each type works differently, but they are all "pings." 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" 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. +Next, a **Welcome to MeshMapper** prompt offers a short tour. Tap **Start Guide** to open the **Quick Guide**, 12 short pages ("Page X of 12") covering connecting, online vs offline, privacy, the antenna setting, CARpeaters, background use, modes, Smart Pinging, map controls, results, your account, and getting help. Tap **Skip Guide** to skip it. You can reopen it any time from **Settings > About & Support > Quick Guide**. + +!!! tip "Privacy options" + Two privacy settings live under **Settings > Wardriving > Privacy**: + + - **Anonymous Mode** renames your radio to "Anonymous" for mesh pings and keeps you off the public leaderboard. It hides your name only: your radio's public key is still used to sign in, and your sessions are still recorded against it. + - **Broadcast My Coordinates** is off by default, so your coordinates are sent only to the MeshMapper server, not over the air. + + You can also wardrive in Offline Mode and never upload your sessions. + +!!! warning "Wardriving in the background" + To keep wardriving on iOS with the screen off or the app in the background, turn on **Background Location** under Settings > General in MeshMapper and allow location access **Always**. Without it, iOS may slow or stop GPS updates when the app is not in the foreground. Android needs no extra location permission, but some phones pause apps when the screen is off; if that happens, set MeshMapper's battery usage to **Unrestricted** in Android settings. --- @@ -63,30 +65,30 @@ After tapping **Continue**, your phone will ask for location permission. Grant " 1. **Navigate to the Connect tab** (the Bluetooth icon in the bottom navigation bar) 2. **Make sure your radio is powered on** and nearby -3. **Tap "Scan for Devices"** to start a Bluetooth scan. Your MeshCore device should appear in the list within a few seconds. +3. **Tap "Scan"** at the bottom of the screen to start a Bluetooth scan. Your MeshCore device should appear in the list within a few seconds. Scan only works when you are inside a MeshMapper zone (or in Offline Mode). 4. **Tap your device** to begin the connection process The app runs a **9-step connection sequence** automatically: | Step | What Happens | |------|-------------| -| 1. Connecting to device | Establishes a BLE connection to your radio | +| 1. Connecting to device | Opens the Bluetooth, TCP, or USB link to your radio | | 2. Protocol handshake | Verifies the app and firmware can communicate | | 3. Querying device info | Retrieves your device's manufacturer string and public key (required for API auth) | | 4. Identifying device | Matches your radio against the device database to determine model and TX power | | 5. Syncing time | Synchronizes your radio's clock with your phone | -| 6. Acquiring API session | Authenticates with the MeshMapper API, gets zone info and regional settings | -| 7. Setting up channel | Creates the #wardriving channel on your radio | -| 8. Initializing GPS | Waits for a GPS lock on your phone | +| 6. Acquiring API slot | Authenticates with the MeshMapper API, gets zone info and regional settings | +| 7. Setting up channel | Makes sure the #wardriving channel exists on your radio | +| 8. Initializing GPS | Starts GPS tracking on your phone | | 9. Connected | Ready to wardrive | Once complete, the Connect tab icon turns **green** and the label changes to "Connected." !!! tip - MeshMapper remembers your last connected device. On future launches, you can tap the remembered device to reconnect quickly without scanning. + MeshMapper remembers your last connected device. On future launches, the **Last Connected Device** card lets you tap **Reconnect** without scanning (or **Forget** it). !!! note "Not just Bluetooth" - Bluetooth is the standard way to connect, but the Connect tab also supports **TCP** (network-attached radios, Android/iOS) and **USB Serial** (Android via OTG cable, or Chrome/Edge on the web). See the [Connection Guide](app_connection_guide.md) for details. + Bluetooth is the standard way to connect, but the Connect tab also supports **TCP** (network-attached radios, such as a Wi-Fi companion) and **USB** (Android only, via an OTG cable). Pick BLE, TCP, or USB in the bar at the bottom of the Connect tab. See the [Connection Guide](app_connection_guide.md) for details. --- @@ -94,18 +96,25 @@ Once complete, the Connect tab icon turns **green** and the label changes to "Co Before you can send a ping, two things need to be set: -1. **External antenna** — On the Map tab, the Controls panel asks "External Antenna?" Tap **Yes** or **No**. - - This is required before any pings can be sent - - Select **Yes** if your antenna has a clear, unobstructed path to the sky (e.g., mag-mount on a car roof, antenna outside a window) - - Select **No** if your radio is inside a vehicle (cup holder, dash), inside a bag, or otherwise obstructed by metal or walls - - The key distinction is whether the signal is obstructed, not just whether it is an external antenna. Being inside a metal car significantly reduces range. - - This matters because the coverage map needs accurate data about signal conditions +1. **External antenna** — On the Map tab, the Controls panel has an **External Antenna** switch with **No** and **Yes** (in landscape it is labelled **Antenna**, with **Internal** and **External**). + - This is required before any pings can be sent (the panel shows "Select antenna option" until you choose) + - Select **No** (Internal) if the antenna is inside a metal vehicle cabin, a metal box, or another enclosure that reduces reception, e.g. the radio and antenna are inside the car + - Select **Yes** (External) if nothing like that blocks the antenna, e.g. a roof-mounted antenna, a handheld radio, or walking with the radio in your pocket + - This does not change your radio or its power. It records how the antenna was set up so the coverage data can be read correctly. + - The app remembers your choice for each radio 2. **Coverage zone** — The status bar shows your zone status: - Green zone code (like "YOW") = you are in a zone and TX is allowed - Red zone code = you are in a zone but TX is at capacity (Passive Mode only) - - Orange dash = you are outside any zone (or GPS is still searching) + - Blue zone code = your region has flood traffic turned off (Passive and Trace only) - Grey zone code = you are in a zone but not yet connected + - Orange dash = you are outside any zone + - Orange "GPS..." = GPS is still searching + +If your device model was not recognised, you may also need to pick a power level on the Connect tab (the panel says "Select power level in Connect tab"). + +!!! note "Flood traffic" + Send Ping, Active Mode, and Hybrid Mode send flood traffic, so they only appear when your region allows it. Regions that have not been set up yet have flood traffic turned off by default. When flood traffic is off, or the zone is at capacity, those buttons are hidden and only Passive and Trace are available. Once both are set, tap **Send Ping**: @@ -116,6 +125,7 @@ Once both are set, tap **Send Ping**: - 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)** - Results appear as markers on the map and entries in the Log tab +- After a manual ping, Send Ping has a 15-second cooldown --- @@ -126,7 +136,7 @@ The status bar sits below the app bar on the Map tab: - **Zone chip** (left): Zone code when in coverage, dash when outside, "GPS..." while acquiring. Tap for details. - **TX**: Channel messages sent (flood the mesh, or scoped if your region has a scope set) - **RX**: Mesh packets passively received -- **DISC**: Discovery requests sent +- **DISC**: Discovery requests that got a response - **TRC**: Successful trace responses - **Upload**: Pings successfully uploaded to MeshMapper servers @@ -136,7 +146,7 @@ Tap any stat chip to see a description of what it means. ## What Happens to Your Data -Every ping you send (TX), mesh packet you passively receive (RX), and discovery response (DISC) is queued for upload to the MeshMapper API. The app batches these uploads (up to 50 at a time) and sends them automatically. You can see the current queue size in Settings under "Data > Queued Pings." +Every ping you send (TX), mesh packet you passively receive (RX), discovery response (DISC), and trace result (TRC) is queued for upload to the MeshMapper API. The app batches these uploads (up to 50 at a time) and sends them automatically. In Offline Mode nothing is uploaded until you upload the saved session yourself from Settings > Data. You can see the current queue size in Settings under "Data > Queued Pings." Your data contributes to the community coverage map at [meshmapper.net](https://meshmapper.net/), helping everyone understand where MeshCore mesh coverage exists. diff --git a/docs/app_how_it_works.md b/docs/app_how_it_works.md index 2b48758..708c264 100644 --- a/docs/app_how_it_works.md +++ b/docs/app_how_it_works.md @@ -18,17 +18,14 @@ This data is aggregated with contributions from other wardrivers on the [MeshMap ## How Bluetooth Communication Works -MeshMapper communicates with your radio over **Bluetooth Low Energy (BLE)** using the UART (serial) service: +MeshMapper talks to your radio over **Bluetooth Low Energy (BLE)**, **TCP** (Wi-Fi), or **USB serial** (Android only). Over BLE it uses the Nordic UART service (`6E400001-…`): -- **TX Characteristic**: Write commands to the device -- **RX Characteristic**: Receive notifications (responses and events) from the device +- The app **writes** commands to characteristic `6E400002-…` (the "RX" characteristic, named from the radio's side) +- The app **receives notifications** (responses and events) on characteristic `6E400003-…` (the "TX" characteristic) -All communication follows the **MeshCore Companion Protocol**, a binary protocol where the app sends commands and the radio responds with data or event notifications. +All communication follows the **MeshCore Companion Protocol**, a binary protocol where the app sends commands and the radio responds with data or event notifications. The same protocol runs over all three links. -**Platform libraries:** - -- Android / iOS: `flutter_blue_plus` -- Web: `flutter_web_bluetooth` +**Bluetooth library:** `flutter_blue_plus` on Android and iOS. --- @@ -36,34 +33,41 @@ All communication follows the **MeshCore Companion Protocol**, a binary protocol When you send a TX ping (manually or via auto-ping), you are sending a **channel message** that floods the mesh: -1. **Message composition**: By default, a short **anonymous token** (a keyed "wire tag" unique to your session and ping). Your GPS coordinates and power level travel to MeshMapper only via the API — they are not in the on-air message. If **Broadcast My Coordinates** is enabled in Settings, your GPS coordinates are appended to the message as well. -2. **Encryption**: AES-ECB with the #wardriving channel key (SHA-256 hash of "#wardriving"). ECB mode is mandated by the MeshCore protocol. Note that anyone with the community channel key can decrypt the message — which is why it carries a token rather than your location by default. -3. **Broadcast and flooding**: The encrypted message is sent via BLE as a GROUP_TEXT packet. It **floods the entire mesh** by default (every repeater relays it). If a **flood scope** is configured by the regional admin, only repeaters within the scope relay it. -4. **Echo listening (5-second window)**: After sending, the app opens a 5-second listening window. Every incoming packet is checked against these criteria, proceeding to step 5 if all of the following conditions are met: - - Packet is of the GROUP_TEXT type - - RSSI is NOT stronger (closer to zero) than -30 dBm (likely a vehicle-mounted "carpeater" if so). This can be overridden by the user in the MeshMapper app settings. - - Channel hash matches that of #wardriving - - Decrypted content matches that of the ping just sent - - Path length is > 0 (the packet has traveled through at least one repeater) -5. **Deduplication**: If the same packet is heard from the same repeater more than once, only the one with the best SNR value is kept. -6. **Queuing**: After the 5-second window closes, the TX ping and its echo results are added to the **upload queue**. A 5-second flush timer starts. When the timer expires, the queue uploads. +1. **Message composition**: By default the message is a short **anonymous token**, `MM:` followed by a keyed "wire tag" unique to your session and ping. Your GPS coordinates and power level travel to MeshMapper only via the API, not in the on-air message. If **Broadcast My Coordinates** is enabled in Settings, your coordinates are appended to the token (`MM::lat,lon`). +2. **Sending and encryption**: The app hands the plain text to your radio with the `CMD_SEND_CHANNEL_TXT_MSG` command on the #wardriving channel. The radio encrypts it with AES-128-ECB, using the #wardriving channel key (the first 16 bytes of the SHA-256 hash of "#wardriving"). ECB mode is mandated by the MeshCore protocol. Anyone with the community channel key can decrypt the message, which is why it carries a token rather than your location by default. +3. **Broadcast and flooding**: The radio transmits it as a group text (GRP_TXT) packet that **floods the entire mesh** by default (every repeater relays it). If a **flood scope** is configured by the regional admin, only repeaters within the scope relay it. +4. **Echo listening (5-second window)**: After sending, the app opens a 5-second listening window. Every incoming packet is checked in this order, and is counted as an echo only if it passes them all: + - Packet is a GRP_TXT packet + - Path length is > 0 (the packet has traveled through at least one repeater) + - If the **first hop** is your own CARpeater: a single-hop packet is dropped; otherwise your CARpeater's hop is stripped and the next repeater is credited, with no SNR/RSSI (those readings belong to your CARpeater) + - Neither the first hop nor the credited repeater is on the region's shared CARpeater list + - The repeater is not excluded by your CARpeater filter + - RSSI is NOT -30 dBm or stronger (closer to zero), which would suggest a vehicle-mounted "CARpeater". This check can be switched off in Settings, and is skipped when a CARpeater hop was stripped. + - Channel hash matches #wardriving + - Decrypted content matches the ping just sent +5. **Which repeater is credited**: An echo that came straight from one repeater (1 hop) is credited to that repeater and goes in the TX ping's results. An echo that traveled through several repeaters (path longer than 1) is credited to the **last** repeater in its path, the one you heard, and is uploaded as a separate RX item at the ping's location. +6. **Deduplication**: If the same repeater is heard more than once, only the reading with the best SNR is kept. +7. **Queuing**: After the 5-second window closes, the TX ping and its echo results are added to the **upload queue**. A 5-second flush timer starts. When the timer expires, the queue uploads. + +A session can send at most **2047** TX pings (the wire tag's counter limit). When it runs out, the app uploads what is queued and disconnects; reconnect to start a new session. ### TX vs RX Queuing TX pings are queued differently from RX observations: -- **TX/DISC/Trace** go directly into the upload queue as a single item (the ping + its results from the listening window). A **5-second flush timer** triggers an upload shortly after. -- **RX observations** go through a **two-stage pipeline**: first the RX Logger batches by repeater (best SNR, 25 meter/30 second flush), then the API queue buffers up to **4 RX entries per repeater** before flushing to the main queue. +- **TX, DISC and Trace** results go directly into the upload queue as items (a TX ping and its echoes are one item; each discovered repeater is one DISC item). A **5-second flush timer** triggers an upload shortly after. +- **RX observations** go through a **two-stage pipeline**: first the RX Logger batches by repeater (best SNR, 25 meter/30 second flush), then the upload queue holds up to **4 RX entries per repeater** before moving them to the main queue. Any more from the same repeater before that move are dropped. --- ## How RX Observations Work -While connected, the **Unified RX Handler** continuously monitors all incoming BLE packets from your radio, regardless of mode. +While an **auto mode is running** (Active, Passive, Hybrid or Trace), the app logs mesh traffic your radio overhears. When no auto mode is running, the only packets it uses are the echoes of a manual ping during its 5-second window. -- Any mesh traffic the radio overhears is processed, validated, and queued for upload +- Mesh traffic the radio overhears is processed, validated, and queued for upload - RX observations are "free data" requiring no transmission from you - They capture other devices' mesh traffic, adding extra coverage data from your location +- An observation needs a GPS fix. Packets heard while the phone has no fix are dropped. ### RX Batching (Aggregation) @@ -91,10 +95,10 @@ After flushing, if you hear the same repeater again, a new batch starts at your Discovery pings use a fundamentally different mechanism than TX channel messages. Instead of flooding the mesh, discovery sends a **direct control data request** (zero-hop) to nearby repeaters. Note: Only repeaters and room servers with firmware 1.10.0 or newer support and will respond to discovery pings. -1. **Request**: ControlData command (0x37) with DISCOVER_REQ flag, requesting responses from repeaters and rooms in direct range. Includes a random 4-byte tag for matching. +1. **Request**: Control data command (0x37) with the DISCOVER_REQ flag, asking repeaters and room servers in direct range to answer. It carries a random 4-byte tag. 2. **Response**: Repeaters respond with node type, public key, and their assessment of signal quality from their end (remote SNR). -3. **Tracking**: Discovery Tracker collects responses during a 7-second window, deduplicates by public key, and filters carpeaters. Gives you **bidirectional** signal quality (how you hear them & how they hear you). -4. **Upload**: "DISC" type data with repeater public key, node type, and bidirectional signal quality. +3. **Tracking**: The app listens for 7 seconds. It accepts answers carrying any tag, so an answer to another phone's discovery heard in that window counts too (the tag is only used to time replies to your own request). Answers are grouped by the repeater's ID (the first 1 to 3 bytes of its public key, following your TX Bytes setting), keeping the best local SNR. Answers from the region's shared CARpeaters, from your own CARpeater, and at -30 dBm or stronger (unless the RSSI filter is off) are dropped. The result is **bidirectional** signal quality (how you hear them & how they hear you). +4. **Upload**: One "DISC" item per repeater, with its public key, node type, and bidirectional signal quality. If nobody answered and **Discovery Drop** is on, a single DISC item with no repeater is uploaded instead. --- @@ -102,9 +106,9 @@ Discovery pings use a fundamentally different mechanism than TX channel messages Trace pings target a specific repeater by hex ID: -1. **Command**: CMD_SEND_TRACE_PATH (0x24) as a zero-hop trace -2. **Response**: If in range, repeater responds with PUSH_CODE_TRACE_DATA (0x89) containing signal quality -3. **Logging**: Successful traces → uploaded to API. Failed traces (no response within 5s) → logged locally, shown as grey markers on noise floor graph. +1. **Command**: CMD_SEND_TRACE_PATH (0x24) as a zero-hop trace. The target ID is 1, 2 or 4 bytes, following your **Trace Bytes** setting. +2. **Response**: If in range, the repeater responds with PUSH_CODE_TRACE_DATA (0x89) containing signal quality +3. **Logging**: Successful traces → uploaded to API. Failed traces (no response within 5s) → logged locally, shown as grey markers on the noise floor graph. --- @@ -115,7 +119,7 @@ Smart Pinging is the app's way of not repeating work the map already shows. It i 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. +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 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 @@ -123,47 +127,64 @@ Smart Pinging is the app's way of not repeating work the map already shows. It i --- +## How Scope Discovery Works + +Scope discovery asks repeaters which **regions (flood scopes)** they carry. It runs when **Scope Discovery** is on (switched on by you, or enforced by the region), your region's server offers it, and your companion firmware is 1.16.0 or newer. + +1. **After a discovery**: The app picks up to 3 of the strongest repeaters the discovery found that are due to be asked. A repeater is due only if nobody has asked it within the refresh interval. +2. **The question**: One at a time, the app sends each one a short anonymous "regions" request, routed directly to it. Your pings are not delayed. +3. **The answer**: The repeater replies with its list of region names (`*` means it passes unscoped traffic). The app uploads it as a `SCOPES` item, always after the DISC item for the discovery that found the repeater. + +See [Scope Discovery](app_settings_reference.md#scope-discovery) for the settings. + +--- + ## 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. +Every overheard (RX) packet goes through a strict validation pipeline before being accepted. If a packet fails any step, it is dropped immediately. ### 1 Path length check - Packet must have traveled through **at least one repeater** (path length > 0) - Direct transmissions from nearby devices are not repeater coverage data +- **Direct-routed** packets are dropped too: their path lists the route still ahead of them, not the repeater you heard + +### 2 Vehicle-mounted "CARpeater" ID check -### 2 Vehicle-mounted "CARpeater" ID check (optional) +- If you have set your CARpeater's public key in the CARpeater Filter: + - **Single hop** from your CARpeater → **dropped** (this is just your own repeater relaying back to you, no real coverage info) + - **Multiple hops** with your CARpeater as the last hop → your CARpeater's hop is **stripped**, and the second-to-last hop is used as the real repeater (the packet traveled through a distant repeater first, then your CARpeater delivered it to you. The distant repeater is the real coverage data. SNR/RSSI are set to null since they reflect your CARpeater's signal, not the distant repeater's.) +- If the repeater about to be credited is on the region's shared **Regional CARpeaters** list → **dropped** -- If you have configured a CARpeater filter with a repeater hex ID in the MeshMapper app settings: - - **Single hop** from your CARpeater → **dropped** (this is just your own repeater relaying back to you, no real coverage info) - - **Multiple hops** with CARpeater as last hop → CARpeater hop is **stripped**, second-to-last hop used as the real repeater (the packet traveled through a distant repeater first, then your CARpeater delivered it to you. The distant repeater is the real coverage data, your CARpeater just happened to be the final relay. SNR/RSSI are set to null since they reflect your CARpeater's signal, not the distant repeater's.) +**No GPS fix**: a packet that passes the checks so far is dropped if the phone has no GPS fix, since it could not be placed on the map. ### 3 RSSI check (CARpeater failsafe) - Signal must be **weaker (farther from zero) than -30 dBm** -- Anything stronger implies the relaying node is right next to you (likely a carpeater) +- Anything stronger implies the relaying node is right next to you (likely a CARpeater) - Acts as a safety net even without the CARpeater ID filter -- Skipped if the Disable RSSI Filter option is ENABLED in app Settings or if CARpeater hop was already stripped +- Skipped if the Disable RSSI Filter option is ENABLED in app Settings or if a CARpeater hop was already stripped ### 4 Packet type check -- Only two types accepted: - - **GROUP_TEXT** (0x15) — Channel messages - - **ADVERT** (0x11) — Node advertisements +- Only two payload types accepted: + - **GRP_TXT** (0x05) — Channel messages + - **ADVERT** (0x04) — Node advertisements -### 5 Channel hash check (GROUP_TEXT only) +### 5 Channel hash check (GRP_TXT only) -- Channel hash must match a **subscribed channel** (#wardriving or regional channels) +- Payload must be at least 3 bytes (channel hash plus MAC) +- Channel hash must match an **allowed channel**: Public, #wardriving, and your region's channels - Prevents random mesh traffic from being counted as coverage data -### 6 Decryption (GROUP_TEXT only) +### 6 Decryption (GRP_TXT only) -- Payload decrypted with the matching channel's AES-ECB key +- Payload decrypted with the matching channel's AES-128-ECB key - Dropped if decrypted data is too short (< 5 bytes) -### 7 Printable character check (GROUP_TEXT only) +### 7 Printable character check (GRP_TXT only) -- At least **60%** of decrypted message must be printable ASCII (codes 32-126) +- At least **60%** of the decrypted message must be printable ASCII (codes 32-126) - Filters corrupted packets that coincidentally have a valid channel hash - 60% threshold allows for emojis and Unicode in legitimate messages @@ -182,10 +203,10 @@ Without this pipeline, the coverage map would be polluted with: Validated packets enter the RX batching pipeline (see [How RX Observations Work](#how-rx-observations-work) above): -1. **Grouped by repeater ID** (last hop in path, the repeater that delivered the packet to you) +1. **Grouped by repeater ID** (last hop in path, the repeater that delivered the packet to you, or the one behind your CARpeater) 2. **Best SNR kept** per repeater. If multiple packets arrive from the same repeater, only the one with the strongest SNR is retained. GPS location is pinned to where you **first** heard that repeater. 3. **Flushed to upload queue** when you move **25 meters** from the first observation OR **30 seconds** pass, whichever comes first -4. The upload queue then buffers up to **4 RX entries per repeater** before adding them to the main batch for API upload +4. The upload queue then holds up to **4 RX entries per repeater** before adding them to the main batch for API upload --- @@ -193,24 +214,26 @@ Validated packets enter the RX batching pipeline (see [How RX Observations Work] The noise floor is the ambient radio energy when no intentional signals are present: -- Polled every **5 seconds** from your radio's hardware stats while in auto-ping mode -- Included with every data point uploaded (TX, RX, DISC, Trace) +- Polled every **5 seconds** from your radio's stats, from the moment you connect +- Included with every TX, RX, DISC and Trace item uploaded - Helps the community understand the radio environment at each coverage point - The noise floor graph overlays ping events on the timeline for visual correlation -- Values are reported as dBm departure from a device's 10th percentile baseline to account for variances between hardware types. See [How Calibration Works](https://wiki.meshmapper.net/layers/#how-calibration-works). +- On the map, MeshMapper shows each reading as its difference from **your own** baseline (the 10th percentile of all your readings), which evens out differences between radios. See [Noise Floor](layers.md#noise-floor). --- ## The Upload Queue -All wardriving data (TX, RX, DISC, Trace) flows through a single persistent upload queue before reaching the MeshMapper API. +All wardriving data (TX, RX, DISC, Trace, plus DEFER and SCOPES items) flows through a single persistent upload queue before reaching the MeshMapper API. -- **Storage**: Hive database on your device. If Hive becomes corrupted, falls back to in-memory queue (data lost if app closes). -- **Batch upload**: Auto-flushes every **15 seconds** on a timer, up to **50 items** per batch. TX/DISC/Trace pings also trigger a **5-second flush** after being queued. -- **Retry logic**: Failed uploads retry up to **5 times** with exponential backoff. Non-retryable errors (invalid data) are discarded immediately. +- **Storage**: Hive database on your device. If Hive becomes corrupted, it falls back to an in-memory queue (data lost if the app closes). +- **Batch upload**: Auto-flushes every **15 seconds** on a timer, up to **50 items** per batch. Queuing a TX, DISC, Trace, DEFER or SCOPES item also triggers a **5-second flush**. On a constrained link (such as satellite) both timers stretch to **60 seconds**. +- **Retry logic**: A batch the server rejects is retried up to **5 times** with exponential backoff. Items that ran out of retries get another chance after the next successful upload. +- **No answer**: If the server can't be reached, or asks the app to wait, the batch is held without using up a retry. +- **Discarded batches**: A batch the server refuses for its data (`gps_inaccurate`, `gps_stale`, `invalid_request`, `zone_disabled`, `outofdate`, `outside_zone`) is dropped rather than retried. Session errors such as `zone_full` also end the session. An expired session refreshes itself and the batch waits. - **Authentication**: Handled automatically by the app -- **Fresh start**: Queue is always cleared on connect and disconnect. Pings without a valid session cannot be uploaded. -- **Offline mode**: When offline, pings accumulate in a separate list instead of the upload queue. They are saved to session files and can be uploaded later from Settings. +- **Fresh start**: The queue is cleared when you connect. When you disconnect, the app uploads what it can first, then clears the rest. During an automatic reconnect after a dropped link, the queue and session are kept. +- **Offline mode**: When offline, pings accumulate in a separate list instead of the upload queue. They are saved to session files and can be uploaded later from Settings > Data. --- @@ -218,18 +241,19 @@ All wardriving data (TX, RX, DISC, Trace) flows through a single persistent uplo A "carpeater" (car + repeater) is a repeater mounted in/on your vehicle. It will always have a very strong signal and does not provide useful coverage data. -**Two filter methods:** +**Three 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**: Set your repeater's full public key in Settings > Wardriving > CARpeater Filter. Echoes from that repeater are stripped before upload. +2. **Your CARpeater**: Set your repeater's full public key in Settings > Wardriving > CARpeater Filter. Its hop is stripped and the repeater behind it is credited instead; packets that only reached your CARpeater are dropped. +3. **Regional CARpeaters**: CARpeaters shared for your region are always dropped, and nothing behind them is credited. -Both can be adjusted or disabled in Settings for testing. +The RSSI threshold can be switched off in Settings (Disable RSSI Filter). See [CARpeater settings](app_settings_reference.md#carpeater). --- ## Multi-Byte Path Support -Each packet carries a "path" showing which repeaters it traveled through, with each hop identified by a hash of the repeater's public key. +Each packet carries a "path" showing which repeaters it traveled through, with each hop identified by the first bytes of the repeater's public key. - **1 byte** (default): 256 possible values, can cause collisions in large networks - **2 bytes**: ~65K values, reduced collisions @@ -239,20 +263,23 @@ Each packet carries a "path" showing which repeaters it traveled through, with e - 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 +- Trace pings have their own **Trace Bytes** setting (1, 2 or 4 bytes) +- Regional administrators can require a specific TX Bytes setting in the admin panel +- When a hop ID matches more than one repeater, MeshMapper only credits it if exactly one repeater fits. See [Duplicate Repeater IDs](duplicaterepeaterid.md#the-rules). --- ## Platform Differences -| Feature | Android | iOS | Web | -|---------|---------|-----|-----| -| BLE library | flutter_blue_plus | flutter_blue_plus | flutter_web_bluetooth | -| Background mode | Foreground service + notification | Background modes (bluetooth-central, location) | Not available | -| Debug logging | File-based | File-based | Browser console (`?debug=1`) | -| Background location | Automatic with foreground service | Requires "Always" permission | N/A | -| App exit option | Yes (Settings) | No | No | -| Audio focus | Transient with ducking | Ambient category | Default | +| Feature | Android | iOS | +|---------|---------|-----| +| BLE library | flutter_blue_plus | flutter_blue_plus | +| Other connections | TCP, USB serial | TCP | +| Background mode | Foreground service + notification | Background modes (bluetooth-central, location) | +| Debug logging | File-based | File-based | +| Background location | Foreground service; Background Location asks for "Allow all the time" | Background Location asks for "Always" | +| App exit option | Yes (Settings > General > Close App) | No | +| Audio focus | Transient with ducking | Ambient category | --- @@ -261,10 +288,10 @@ Each packet carries a "path" showing which repeaters it traveled through, with e Your wardriving data contributes to the public coverage map at [meshmapper.net](https://meshmapper.net/). The data includes: - GPS coordinates, repeater signal quality, noise floor, device power level -- No personal information beyond what is inherent to the mesh protocol (device public key for auth) +- Your device's public key, used to authenticate your session **On-air privacy:** your GPS position is not broadcast over the mesh by default — TX pings carry a short anonymous token, and coordinates go only to the MeshMapper API. Enable "Broadcast My Coordinates" only if you want your live position visible on the air. -If you prefer not to broadcast your device name either, enable Anonymous Mode in Settings. +If you prefer not to broadcast your device name either, enable Anonymous Mode in Settings. Your device is renamed "Anonymous" and you are left off the public leaderboard, but your sessions are still recorded against your public key. -You can also view and manage the data you've contributed through the [My MeshMapper portal](portal.md). +See [Privacy](privacy.md) for what is collected and kept. You can also view and manage the data you've contributed through the [My MeshMapper portal](portal.md). diff --git a/docs/app_overview.md b/docs/app_overview.md index d22f447..864fe05 100644 --- a/docs/app_overview.md +++ b/docs/app_overview.md @@ -1,13 +1,18 @@ # Wardriving App -MeshMapper is a community-driven wardriving app for MeshCore mesh network devices. It lets you connect to a MeshCore radio over Bluetooth, send GPS-tagged pings across the mesh, and contribute coverage data to the [MeshMapper community map](https://meshmapper.net/). +MeshMapper is a community-driven wardriving app for MeshCore mesh network devices. It connects to your MeshCore radio over Bluetooth, TCP (network/Wi-Fi), or USB (Android), sends pings across the mesh, and adds what it hears to the [MeshMapper community map](https://meshmapper.net/). Your location goes only to the MeshMapper server; by default, pings on the air carry an anonymous token, not your coordinates. -The app is available on Android, iOS, and Chromium-based browsers (Chrome/Edge). The source code is available on [GitHub](https://github.com/MeshMapper/MeshMapper_Flutter_App). +The app is available for Android and iOS: + +[Download on the App Store](https://apps.apple.com/us/app/meshmapper/id6758073991) | [Get it on Google Play](https://play.google.com/store/apps/details?id=net.meshmapper.app) + +The source code is on [GitHub](https://github.com/MeshMapper/MeshMapper_Flutter_App). New to the app? The built-in **Quick Guide** walks you through the basics on first launch, and you can reopen it any time from **Settings > About & Support > Quick Guide**. - [**Getting Started**](app_getting_started.md) - Installation, first launch, and your first ping - [**App Tabs**](app_tabs.md) - Detailed walkthrough of the Map, Log, History, Connect, and Settings tabs - [**Wardriving Modes**](app_wardriving_modes.md) - Manual, Hybrid, Passive, Active, and Trace modes explained - [**Settings Reference**](app_settings_reference.md) - Every setting explained - [**Connection Guide**](app_connection_guide.md) - Device scanning, the 9-step connection process, reconnection, and offline mode -- [**How It Works**](app_how_it_works.md) - Technical deep-dive into Bluetooth communication, packet filtering, and data pipelines +- [**How It Works**](app_how_it_works.md) - Technical deep-dive into radio communication, packet filtering, and data pipelines - [**Troubleshooting**](app_troubleshooting.md) - Common issues and how to resolve them +- [**Third Party API**](app_third_party_api.md) - Forward your wardriving data to your own endpoint (for developers) diff --git a/docs/app_settings_reference.md b/docs/app_settings_reference.md index 11f56c7..be1e2f5 100644 --- a/docs/app_settings_reference.md +++ b/docs/app_settings_reference.md @@ -3,7 +3,7 @@ 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 Settings and on each folder page when this is the case. Stop auto-ping to change locked settings. + Some settings are locked while auto-ping is running. An amber "Some settings locked during auto-ping" banner appears at the top of Settings and on the folder pages that have locked settings. Stop auto-ping to change them. --- @@ -28,14 +28,15 @@ Complete reference for every setting in MeshMapper. The Settings tab is a list o #### Sound Notifications - Plays sounds on ping events. Sounds follow your phone's **media volume**. +- **Disabled by default** - 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** (on by default): Sound when a TX ping or discovery is sent + - **Response Received** (on by default): Sound when a repeater echo or RX is received + - **Disconnect Alert** (off by default): Triple beep when an automatic mode stops unexpectedly, such as when your radio disconnects - 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) +### Location #### Background Location @@ -72,7 +73,7 @@ Complete reference for every setting in MeshMapper. The Settings tab is a list o ### Map Tiles -#### Offline Maps (Mobile only) +#### Offline Maps Download map areas to your device for wardriving without a data connection. Opens the **Offline Maps** screen: @@ -83,6 +84,7 @@ Download map areas to your device for wardriving without a data connection. Open - 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 +- While it is on, **Coverage Overlay Opacity** and **Grid Mode** are hidden ### Coverage Overlay @@ -94,13 +96,13 @@ Download map areas to your device for wardriving without a data connection. Open - **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 +- Matches the Grid Mode option on the meshmapper.net map - Also sets the square size [Smart Pinging](#smart-pinging) uses, so what is deferred matches what is painted #### Color Vision - 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 +- Applies to the coverage overlay and map colours, matching the meshmapper.net map's accessibility palettes ### Markers @@ -117,6 +119,11 @@ Download map areas to your device for wardriving without a data connection. Open - Shows the **Top Heard** overlay on the map with the best 3 repeaters by SNR from your most recent ping - Disabled by default +#### Larger Top 3 Overlay + +- Makes the Top Heard overlay bigger for easier reading +- Shown only while **Top Repeaters on Map** is on. Disabled by default. + --- ## Wardriving @@ -129,7 +136,8 @@ Download map areas to your device for wardriving without a data connection. Open - 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 +- A confirmation dialog appears every time you enable it. Disabling asks for confirmation only while connected. +- Your public key is still sent to authenticate your session, so Anonymous Mode hides your name, not your device. You also do not appear on the public leaderboard. - Cannot change while auto-ping is running #### Broadcast My Coordinates @@ -148,7 +156,7 @@ How frequently pings are sent in Active, Hybrid, and Trace modes: - **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. Faster choices are greyed out and marked "Set by Regional Admin". +- Regional admin may enforce a minimum interval. Faster choices are greyed out and marked "Set by Regional Admin — slower intervals reduce congestion in your region". If your interval is faster than the region allows, it is raised when you connect. !!! 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. @@ -162,7 +170,7 @@ Minimum distance you must move before the next auto-ping. Prevents spamming from - **Minimum**: 25m (enforced by the app) !!! note - Does not apply to manual pings. Cannot be changed during auto-ping. + Applies to every auto mode (Active, Hybrid, Passive and Trace). Does not apply to manual pings. Cannot be changed during auto-ping. #### Smart Pinging @@ -171,9 +179,11 @@ Defers auto pings in squares that already have recent coverage, so your airtime - **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. +- **Show only recent coverage** (off by default): hides older coverage squares on the map so only coverage inside your window shows, which makes gaps easier to see. Shown only while the switch is on. +- **Show Deferred Markers** (on by default): shows hollow circles on the map where pings were deferred. 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. +- May be enforced by regional admin (shown in amber). When enforced, the switch is locked on and the window is the region's (1, 3, 7, 14 or 30 days). - Cannot be changed during auto-ping #### Scope Discovery @@ -182,22 +192,23 @@ After each discovery, asks the repeaters it found which scopes they carry (the n - **Disabled by default** - Tap the **(i)** beside the switch for details inside the app -- **Check every**: the window, in days, that makes a scope answer from a repeater count as fresh. Enter any whole number from **7 to 365**. Default **14 days**. Shown only while the switch is on. +- **Ask repeaters again after**: the window, in days, that makes a scope answer from a repeater count as fresh. Enter any whole number from **7 to 365**. Default **14 days**. Shown only while the switch is on. - May be enforced by regional admin (shown in amber). When enforced, the switch is locked on and the window is the region's. -- Requires companion firmware **1.16.0 or newer**. **1.17.0 or newer is recommended**, see below. +- Requires companion firmware **1.16.0 or newer**. **1.17.0 or newer is recommended**, see below. On older firmware the app shows "Your radio needs firmware v1.16.0 or newer for this." +- A small **Scopes** badge shows on the running mode button while the app is asking - Cannot be changed during auto-ping **Companion firmware 1.16 and a full contact list.** To ask a repeater that is not saved as a contact on your radio, the radio needs a free slot in its contact list. Companion firmware 1.16 cannot make that room when the list is full, so it refuses the request and nothing is sent. The log shows **Radio contact list full**, and from then on, for the rest of that connection, the app only asks repeaters that are saved as contacts. The Errors tab in the log also gets one entry explaining it. Companion firmware **1.17.0 or newer** fixes it by keeping room for these requests. Removing some contacts from your radio also works. **Why a repeater may not answer.** "No response from repeater" in the log is normal and does not mean the repeater is broken or out of date: -- **Each repeater answers at most 4 anonymous requests every 3 minutes.** That limit is built into the repeater firmware and is shared by everyone asking it anything anonymously (scope, owner and clock requests, from any app). Once it is used up, the repeater stays silent until the 3 minutes pass. Busy repeaters on high sites, heard by many radios, reach this limit most often. +- **Repeaters only answer a few anonymous requests in a short time.** That limit is built into the repeater firmware and is shared by everyone asking it anything anonymously, from any app. Once it is used up, the repeater stays silent for a few minutes. Busy repeaters on high sites, heard by many radios, reach this limit most often. - **The answer can be lost on the way back.** An answer is longer than a discovery reply, so a repeater at the edge of range, or on a busy channel, can answer discovery and still miss this one. -- **Older repeater firmware ignores the request.** Repeaters need firmware **1.12.0 or newer** to answer. +- **Older repeater firmware ignores the request.** A repeater that does not answer is not marked as checked, but your phone leaves it alone for a while before asking again: 15 minutes after the first miss, doubling after each further miss, up to 2 hours. An answer clears that wait. This keeps one phone from using up a busy repeater's limit. Nothing is uploaded for a request that goes unanswered. -While scope discovery is on, the app also refreshes its repeater list when Passive or Hybrid starts and every 15 minutes while it runs, so a repeater another driver has just checked is skipped sooner. +While scope discovery is on, the app also refreshes its repeater list when Passive or Hybrid starts (if the list is more than 5 minutes old) and every 15 minutes while it runs, so a repeater another driver has just checked is skipped sooner. #### Auto-Stop After Idle @@ -224,17 +235,17 @@ Strips your own CARpeater from results. Switching it on for the first time opens #### Regional CARpeaters -- 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". +- Shows how many CARpeaters have been shared for your region ("Filtering N regional CARpeaters"). Tap it for the list: each entry shows the repeater's name and the first 16 characters of its key. 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. #### 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. +By default, the app drops any packet with RSSI of -30 dBm or stronger (closer to 0), 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) +- Default: off. The subtitle reads "Drops signals stronger than -30 dBm". - Enabling allows **all signal strengths** through -- Confirmation dialog warns about community map impact before enabling +- A **Disable RSSI Filter?** dialog warns about community map impact before enabling - Cannot be changed during auto-ping ### Modes @@ -242,16 +253,16 @@ By default, the app drops any packet with RSSI equal to or stronger (closer to 0 #### Flood Traffic - Shows or hides the **Active Mode**, **Hybrid Mode**, and manual **Send Ping** controls (everything that sends flood channel messages) -- **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) +- **Off on a fresh install**, so only Passive and Trace modes appear on the Map tab until you connect. Each time you connect in a region that allows flood traffic, the app turns it on. +- Locked off if your regional admin has disabled flood traffic for your region (shown with a blue "Set by Regional Admin" note) - Cannot be changed during auto-ping #### Hybrid Mode -- Alternates between TX channel messages and discovery requests each interval +- Subtitle: "Combines Active and Passive modes". 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. Tap the **(i)** beside the switch for how the interval timing works. -- May be locked by regional admin (shown in amber when enforced) +- Enabled by default. Tap the **(i)** beside the switch for how the interval timing works. +- A regional admin can enforce it (shown in amber). When enforced, the switch is locked on. - Cannot be changed during auto-ping #### Discovery Drop @@ -260,7 +271,7 @@ By default, the app drops any packet with RSSI equal to or stronger (closer to 0 - Helps identify dead zones for network planning - Requires repeater firmware **1.10+** to respond to discovery requests - Disabled by default -- May be enforced by regional admin (shown in amber when set) +- May be enforced by regional admin (shown in amber). When enforced, the switch is locked on. - Confirmation dialog before enabling - Cannot be changed during auto-ping @@ -316,7 +327,7 @@ This is separate from TX Bytes because traces use a different encoding in the Me #### Delete Channel on Disconnect - **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. +- **Disabled**: The channel stays on your radio after you disconnect. --- @@ -336,6 +347,7 @@ Shows how many items are waiting to be uploaded, with two actions beside the cou #### Clear Map Markers - Removes all TX, RX, discovery, and trace markers from the map display +- Confirmation dialog included - Does not affect uploaded data or the upload queue ### Offline Sessions @@ -348,15 +360,17 @@ Sessions recorded in Offline Mode. Each session shows: **Actions per session:** -- **Download**: Save the raw JSON to your device (via the system share sheet on mobile). Always available. +- **Download**: Save the raw JSON to your device (via the system share sheet). Always available. - **Upload**: Send to MeshMapper servers. Shown until the session has been uploaded. -- **Delete**: Remove from local storage +- **Delete**: Remove from local storage (asks for confirmation) + +Uploading needs a GPS fix, because the server checks your current location. Without one you see "GPS required - enable location services to upload". The radio usually does not need to be connected. 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) +## MeshMapper Account *Sign in to link your radios* @@ -382,6 +396,12 @@ Shown once you are signed in, when the server provides it: your **Points**, **Gr !!! 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. +### My Repeaters + +- Lists the repeaters you have logged in to as an admin. Each row shows the repeater's name and key prefix, plus its region when known. +- Tap a row to open that repeater's manage sheet +- With none yet, it says "No repeaters claimed yet". To add one, pick a repeater on the map and tap **Manage** to log in with its admin password. + --- ## API Endpoints @@ -441,17 +461,22 @@ This folder appears once an Apple Watch has been paired with your phone, and sta ### Support +#### Quick Guide + +- Opens the in-app guide to connections, modes, mapping, and data + #### Submit Feedback - 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) +- Can attach debug log files (select which files to include) -#### Debug Logs (Mobile only) +#### Debug Logs - Writes detailed debug logs to files on your device +- **Enabled by default.** If you switch it off, the app remembers that. - Orange "LOGGING" badge when active -- Timestamped entries, auto-rotate (max 10 files, max 4.5 MB per file) -- Always disabled on app start (must re-enable each session) +- Timestamped entries. The app keeps the newest 10 files and deletes older ones. +- Files larger than 4.5 MB are uploaded in parts **When logs exist:** diff --git a/docs/app_tabs.md b/docs/app_tabs.md index 1a5b90d..bed6682 100644 --- a/docs/app_tabs.md +++ b/docs/app_tabs.md @@ -3,9 +3,9 @@ MeshMapper has five tabs accessible from the bottom navigation bar: - **Map** - Primary wardriving interface -- **Log** - Ping and error history +- **Log** - Ping, scope, and error history - **History** - Past session playback and noise floor graphs -- **Connect** - Device connection management (Bluetooth, TCP, USB) +- **Connect** - Device connection management (Bluetooth, TCP, USB). The label changes to **Connected** and the icon turns green once you are connected. - **Settings** - App configuration --- @@ -32,12 +32,21 @@ In portrait orientation, the top bar shows: Below the app bar is the status bar with tappable stat chips: -- **Zone chip** (left): Your current zone code. Tap for details. The popup changes based on your state: zone name and TX slots available (green), zone at TX capacity with Passive Mode suggestion (red), distance to nearest zone (orange), or "Connect to a device to start wardriving" (grey, when in zone but not connected). +- **Zone chip** (left): Your current zone code. Tap for details. What it shows: + - **Green** zone code: in a zone, TX slots available (the popup shows how many) + - **Red** zone code: in a zone, but the zone is at TX capacity, so only Passive works + - **Blue** zone code: your regional admin has turned flood traffic off, so Active and Hybrid are unavailable (Passive and Trace still work) + - **Grey** zone code: in a zone but not connected ("Connect to a device to start wardriving") + - **Orange "—"**: outside any zone (the popup shows the nearest zone and its distance) + - **Orange "GPS..."**: GPS is still searching + - **Grey "OFF"**: location is turned off on your phone + - **Red "!"**: location permission was denied + - **Grey "-"**: Offline Mode (zone checks are paused) - **TX** (green): Channel messages you have sent. These are flood messages that propagate across the mesh (or are regionally scoped if your zone admin has set a scope). - **RX** (purple): Mesh packets passively received. -- **DISC** (cyan): Discovery requests sent. -- **TRC** (blue diamond): Successful trace responses. -- **Upload**: Pings successfully uploaded to the server. +- **DISC** (cyan): Discovery requests that got a response. +- **TRC** (cyan, route icon): Successful trace responses. +- **Upload** (teal): Pings successfully uploaded to the server. Each stat chip animates with a bounce effect when its count increments, making it easy to notice activity. Tap any chip to see a description of what it tracks. @@ -51,21 +60,24 @@ The map shows your current position and wardriving data. - 10m or better (green) - 10-30m (orange) - Worse than 30m (red) - - "No GPS" if there is no fix (black) + - "No GPS" in grey if there is no fix - **Distance from last ping**: How far you have moved since your last ping. Helps you see at a glance whether you have met the minimum distance requirement for auto-ping modes. +- **Altitude**: Your current altitude, when the phone reports one. #### Map Controls Expand the map controls panel to access: - **Map Style**: Cycle between Liberty (standard), Dark, Light, and Satellite map styles -- **Coverage Overlay**: Toggle the MeshMapper community coverage overlay on the map. Shows coverage data reported by all wardrivers in your zone. Only available when in an onboarded region/zone. -- **Repeaters**: Show or hide repeater markers -- **Region Boundary**: Show or hide your region's boundary line and label -- **Auto-Follow**: Centers the map on your GPS position as you move -- **Always North**: Keeps north at the top. When disabled, the map can rotate with your heading. +- **Coverage Overlay**: Toggle the MeshMapper community coverage overlay on the map. Shows coverage data reported by all wardrivers in your zone. Only shown when you are in an onboarded zone. +- **Repeaters**: Show or hide repeater markers (shown when repeaters are loaded) +- **Region Boundary**: Show or hide your region's boundary line and label (shown when your region has a boundary) +- **Center on Position**: Centers the map on your GPS position and keeps following you as you move (the tooltip then reads "Following GPS"). Off by default; tap it again to stop following. +- **Always North**: Keeps north at the top. When disabled, the map rotates with your heading. - **Rotation Lock**: Disables rotation gestures entirely -- **Legend**: Opens a legend showing what the map markers and colours mean +- **Legend & Info**: Opens a legend explaining the map markers, coverage colours, repeater states, and sounds + +The app remembers your follow, north, and rotation choices. #### Markers @@ -81,8 +93,9 @@ These show what **your device** observed locally over BLE. The app only knows wh - **RX** (purple): You passively received a message from the mesh - **DISC (success)** (cyan): You sent a discovery request and a repeater responded - **DISC (fail)** (grey/red): You sent a discovery request but no repeater responded. Shown as red if your region has "Count DISC as failed" enabled, meaning the backend will track a failed discovery as no coverage at that location. -- **TRC (success)** (blue diamond): A trace reached the target repeater +- **TRC (success)** (cyan): A trace reached the target repeater - **TRC (fail)** (grey): A trace got no response +- **Deferred** (hollow yellow ring): [Smart Pinging](app_wardriving_modes.md#smart-pinging) held a ping because this square already has recent coverage. You can hide these with **Show Deferred Markers** in Settings > Wardriving. **Coverage overlay markers** (when coverage overlay is enabled): @@ -95,24 +108,24 @@ 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) 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. +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 a few seconds later, so you can watch your coverage appear as you drive. **Tap to inspect:** - **Tap a coverage cell** to open a summary of its pings, with dashed connection lines fanning out to every repeater that heard that spot (each line labelled with distance). -- **Tap a repeater** to see its details plus all the coverage cells it has been heard from, colour-coded by status, while the rest of the map dims so its footprint stands out. +- **Tap a repeater** to see its details plus all the coverage cells it has been heard from, colour-coded by status, while the rest of the map dims so its footprint stands out. The repeater sheet also has a **Manage** button for logging in to a repeater you administer (it needs the repeater's full key and admin password). -If "Top Repeaters on Map" is enabled in Settings, a **Top Heard** overlay appears on the map. +If **Top Repeaters on Map** is enabled in Settings > Map, a **Top Heard** overlay appears on the map. **Larger Top 3 Overlay** makes it bigger. **Top 3 slots**: Shows the best 3 repeaters by SNR from your most recent ping, fully replacing on each new ping. If a ping gets no responses, the previous results stay visible. Each row has a coloured dot indicating the ping type: - TX ping (green) - Active/Hybrid channel message - Discovery ping (cyan) - Passive/Hybrid query -- Trace ping (blue diamond) - Trace mode, specific repeater +- Trace ping (cyan) - Trace mode, specific repeater **RX slot**: A 4th row shows the strongest passively overheard repeater (purple) within a rolling window that matches your auto-ping interval (15s, 30s, or 60s). -Each row also shows the repeater's hex ID and SNR value, colour-coded: green (good, above 5), orange (okay, -1 to 5), red (poor, below -1). +Each row also shows the repeater's hex ID and SNR value, colour-coded: green (good, above 5), orange (okay, above -1 up to 5), red (poor, -1 or below). The overlay clears when you stop auto-ping, switch modes, disconnect, or clear pings/logs. @@ -130,13 +143,17 @@ Top Heard The control panel floats at the bottom of the map and contains everything you need to wardrive: -- **External Antenna Selector**: A "Yes / No" toggle that you must set before sending any pings. See [Getting Started](app_getting_started.md) for when to select Yes vs No. -- **Send Ping**: Sends a single channel message to #wardriving that floods the entire mesh (or is scoped to your region), then listens 5 seconds for repeater echoes. Disabled if you haven't set your antenna preference, don't have GPS, or aren't in a zone. -- **Hybrid / Active Mode**: Starts automated wardriving at your configured interval. Hybrid Mode (default) alternates between channel messages and discovery requests. See [Wardriving Modes](app_wardriving_modes.md) for details. +- **External Antenna Selector**: A **No / Yes** switch (in landscape: **Antenna**, **Internal / External**) that you must set before sending any pings. It is remembered for each radio. See [Getting Started](app_getting_started.md#your-first-ping) for which to choose. +- **Send Ping**: Sends a single channel message to #wardriving that floods the entire mesh (or is scoped to your region), then listens 5 seconds for repeater echoes, followed by a 15-second cooldown. Disabled until you have set your antenna, have GPS, and are in a zone. +- **Hybrid / Active Mode**: Starts automated wardriving at your configured interval. Hybrid Mode (on by default) alternates between channel messages and discovery requests. See [Wardriving Modes](app_wardriving_modes.md) for details. - **Passive Mode**: Discovery-only mode (no channel messages, no mesh flooding). Sends discovery requests every 30 seconds and passively monitors mesh traffic. -- **Trace Mode**: Target a specific repeater by its hex ID and send trace path requests at your configured interval. +- **Trace Mode**: Target a specific repeater by typing its hex ID, or tap **Choose repeater** to pick one from a list. Sends trace path requests at your configured interval. Once a repeater is picked, you can also open **Manage repeater** from here. - **Help**: Opens a bottom sheet explaining what each button does. +Send Ping and Hybrid/Active only appear when your region allows flood traffic and the zone has a free TX slot. If the region has flood traffic off (the default for regions that are not set up yet) or the zone is full, only Passive and Trace are shown. In Offline Mode they show **Passive only** and are disabled. + +When something is missing, a hint appears under the buttons, such as "Select antenna option", "Select power level in Connect tab", or "Waiting for GPS". + You can minimize the control panel to a compact bar showing just the essential buttons, or hide it entirely (a floating "Controls" button appears to bring it back). ### Landscape Mode @@ -147,29 +164,29 @@ In landscape orientation, the app removes the traditional app bar and replaces i ## Log Tab -The Log tab shows a detailed record of all your wardriving activity, organized into two sub-tabs: **All Pings** and **Errors**. +The Log tab (titled **Logs**) shows a detailed record of all your wardriving activity, organized into two sub-tabs: **All Pings** and **Errors**. Each tab label shows its entry count. ### All Pings -A unified chronological view of every TX, RX, DISC, and Trace event. At the top: +A unified chronological view of every TX, RX, DISC, Trace, and scope event. At the top: - **Search bar**: Filter entries by repeater name or hex ID. Searching by name finds all repeaters whose name contains the query. Searching by hex ID matches IDs that start with the query. -- **Filter bar**: Four toggleable segments (TX, RX, DISC, TRC) each with a count badge. Tap to show/hide that type. At least one must remain active. +- **Filter bar**: Five toggleable segments (TX, RX, DISC, TRC, SCP) each with a count. Tap to show/hide that type. At least one must remain active. **SCP** entries are scope requests the app sent to repeaters. Each entry is a card showing: -- **Type badge**: Colour-coded label (green TX, purple RX, cyan DISC, cyan diamond TRC). TX entries are channel messages that flooded the mesh (or were regionally scoped). +- **Type badge**: Colour-coded label (green TX, purple RX, cyan DISC, cyan TRC, amber SCP). TX entries are channel messages that flooded the mesh (or were regionally scoped). - **Timestamp**: When the event occurred - **Location**: GPS coordinates at the time of the event - **Repeater table**: - - TX: Table of repeaters that echoed your message, with Node ID, SNR, and RSSI + - TX: Table of repeaters that echoed your message directly, with Node ID, SNR, and RSSI, plus a **Multi-hop Repeats** table for echoes that came back over more than one hop - RX: Single repeater row - DISC: Table with RX SNR, RX RSSI, and TX SNR - Trace: Target repeater and signal quality **Tapping a card** navigates to the Map tab and centers on that event's GPS coordinates. -**Tapping a repeater ID** in any table opens a popup showing matching repeaters from the mesh database. Each match shows the repeater's name, a coloured hex ID badge, distance from your current GPS position (sorted closest first), and an Active/Stale status badge. For discovery pings, the popup uses exact 4-byte public key matching for precise identification. For TX/RX pings (which only have 1-byte path IDs), it uses prefix matching, so multiple repeaters may appear if they share the same first byte. +**Tapping a repeater ID** in any table opens a popup showing matching repeaters from the mesh database. Each match shows the repeater's name, a coloured hex ID badge, distance from your current GPS position (sorted closest first), and an Active/Stale status badge. For discovery pings, the popup matches the repeater's full public key for precise identification. For TX/RX pings (which only carry short 1 to 3 byte path IDs), it uses prefix matching, so multiple repeaters may appear if they share the same ID. ### Errors @@ -179,20 +196,20 @@ The Errors sub-tab shows warnings and errors that occurred during your session: - **Warning** (orange): Warning conditions that may need attention - **Error** (red): Errors that likely affected functionality -A badge appears on the Log tab icon when there are unread errors. +A badge appears on the Log tab icon whenever there are entries in the Errors tab. ### Log Actions The overflow menu (⋮) in the top right offers: - **Copy CSV**: Copies the current tab's data to your clipboard in CSV format. If you have a search filter active, only filtered entries are exported. -- **Clear all logs**: Removes all TX, RX, DISC, Trace, and error log entries. +- **Clear all logs**: Removes all log entries, including errors. --- ## History Tab -The History tab (titled **Session History**) lists your past wardriving sessions. Each session card offers two views: +The History tab (titled **Session History**) lists your past wardriving sessions (Active, Hybrid, Passive, and Trace). If you have none yet, it shows "No sessions recorded yet". Each session card offers two views: - **View on Map**: Replays the session's pings as markers on the map, zoomed to fit the session's area. Tap any marker for the same detail sheets as during live wardriving. - **Noise Floor**: Opens the interactive noise floor graph for that session (see below). @@ -209,13 +226,13 @@ The noise floor is the baseline level of radio signal present in the environment - **-100 to -90 dBm**: Moderate noise (orange) - **Above -90 dBm**: High noise, may interfere with mesh communication (red) -MeshMapper polls your radio's noise floor every 5 seconds while connected and in auto-ping mode. +MeshMapper reads your radio's noise floor every 5 seconds while connected, and records it into the session while a wardriving mode is running. ### Session List Each session card shows: -- **Mode icon**: Upload arrow for Active/Hybrid, Ear for Passive +- **Mode icon**: Paper plane for Active, two arrows for Hybrid, a target for Trace, an ear for Passive - **Mode name and date**: When the session started - **Duration**: How long the session lasted - **Sample count**: How many noise floor readings were taken @@ -225,23 +242,25 @@ The currently active session appears at the top with a green **"LIVE"** badge. ### Full-Screen Graph -Tap a session to open the full-screen interactive graph: +Tap the **Noise Floor** button on a session card to open the full-screen interactive graph: - **Noise floor line**: Colour-coded by level (green/orange/red) over time - **Event markers**: Coloured dots marking when ping events occurred: - TX channel message (green) - heard by a repeater (success) - TX channel message (red) - not heard + - TX Multi-hop - echoed back only over multi-hop paths - Passive RX received (purple) - Discovery got a response (cyan) - Discovery with no response (grey) - or failed discovery if "Count DISC as failed" is enabled at the region level - - Trace got a response (blue diamond) + - Trace got a response (cyan) - Trace with no response (grey) + - Deferred (hollow yellow ring) - a ping Smart Pinging held back **Interactions**: - **Pinch to zoom** on a specific time range (minimum 10-second visible window) - **Drag to pan** across the timeline -- **Tap a marker** to open a detail sheet with event type, timestamp, interpolated noise floor, and repeater table +- **Tap a marker** to open a detail sheet with event type, timestamp, noise floor, location, and repeater table, plus a **View on Map** button - **Reset zoom** (top right) returns to full session view Live sessions update every 2 seconds. If the session ends while you are viewing it, the "LIVE" badge disappears and the graph becomes a static historical view. @@ -254,47 +273,48 @@ Use the trash icon in the top right to delete all saved sessions. The current ac ## Connect Tab -The Connect tab manages your device connection. Its appearance changes based on your connection state. +The Connect tab (titled **Connection**) manages your device connection. Its appearance changes based on your connection state. A bar at the bottom holds the **Go Offline / Go Online** button, the main action button (Scan, Connect, Cancel, or Disconnect), and, while disconnected, the connection method picker. ### Connection Methods -A selector at the top lets you choose how to connect to your MeshCore device: +The picker in the bottom bar lets you choose how to connect to your MeshCore device: -- **BLE** (Bluetooth Low Energy) — available on all platforms. The standard way to connect. -- **TCP** — available on Android and iOS. Connect to a network-attached MeshCore device by host and port (default port 5000), e.g. via a WiFi companion or a ser2net bridge. Saved connections are remembered. -- **USB** — available on Android (USB OTG cable) and in the web app (Chrome/Edge via Web Serial). Connect your radio directly with a cable. +- **BLE** (Bluetooth Low Energy) — the standard way to connect. +- **TCP** — connect to a network-attached MeshCore device by host and port (default port 5000), e.g. via a Wi-Fi companion or a ser2net bridge. Connections that succeed are kept under **Saved Connections** for next time. +- **USB** — Android only, with a USB OTG cable. Tap **Refresh** to list connected devices. ### Zone Status Bar -Shown across all connection states when GPS is available: +Shown at the top of the tab (except while connecting or reconnecting): -- **Left**: City name of your current zone and IATA code. If you are outside a zone, shows distance to the nearest one. -- **Right**: Open TX slots (e.g. "3/5 Open"), colour-coded: green (plenty available), orange (2 or fewer left), red (none available) +- **Left**: City name of your current zone and its IATA code. Otherwise it shows the current state, such as "Outside Zone", "Checking Zone...", "Maintenance", "No Internet", "Clock Out of Sync", "GPS Unavailable", "Airborne", or "-" in Offline Mode. +- **Right**: Open TX slots (e.g. "3/5 Open"), colour-coded: green (3 or more), orange (1 or 2 left), red (none available). If your region has flood traffic off, it shows a blue **Flood Off** chip instead; tap it for details. ### Disconnected -- "Go Offline" / "Go Online" button to toggle offline mode -- "Scan for Devices" button to start a BLE scan. Once scanning, a list of discovered devices appears with signal strength. -- Your last connected device shown for quick reconnection +- **Scan** button to start a BLE scan. It is only enabled when you are inside a zone (or in Offline Mode) and not blocked by maintenance or an airborne check. While scanning it becomes **Cancel**. Discovered devices appear in a list with signal strength. With no devices, it shows "Tap Scan to search for MeshCore devices". +- A **Last Connected Device** card with **Reconnect**, **Scan**, and **Forget** buttons +- **Go Offline** / **Go Online** to toggle Offline Mode ### Connecting -- Progress indicator showing the current step of the 9-step connection process -- Cancel button to abort the connection +- Progress indicator showing the current step of the 9-step connection process (for example "Acquiring API slot..."), with "Step X of 9" +- There is no Cancel button during these steps. **Cancel** does appear while scanning, while auto-reconnecting ("Attempt N of 3"), and while the app is searching for or switching zones. ### Connected -- **Radio Info**: +- **Device card**: - **Companion name**: The name of your connected MeshCore device - - **Power Level**: The TX power your device is reporting. Tap to open the power level selector (locked during auto-ping). If your device model was auto-detected, a green banner shows the detected model and wattage. Options: ≤22dBm (0.3W), 28dBm (0.6W), 30dBm (1.0W), 33dBm (2.0W). A checkmark shows the recommended value for your device. If you override the auto-detected power, a confirmation dialog appears. "Reset to Auto" restores auto-detection. This only affects what is reported to the API, it does not change your radio's actual output. + - **Detail chips**: Hardware model, firmware version, and platform (when known) + - **Power Level**: The TX power your device is reporting. Tap to open the power level selector (locked during auto-ping). If your device model was auto-detected, a banner shows the detected model and wattage. Options: ≤22dBm (0.3W), 28dBm (0.6W), 30dBm (1.0W), 33dBm (2.0W). A checkmark shows the recommended value for your device. If you override the auto-detected power, a confirmation dialog appears. "Reset to Auto" restores auto-detection. This only affects what is reported to the API, it does not change your radio's actual output. + - **Radio**: Your radio's frequency, bandwidth, spreading factor, and coding rate - **Public Key**: Your device's unique public key, used for authentication with the MeshMapper API. Tap to copy to clipboard. - - **Registered via**: Shows your device's registration level. Devices can be registered as anonymous (no contact info), or with a signed contact URI that links the device to a MeshCore identity. Higher registration levels may grant access to additional features. -- **Regional Settings**: - - **Zone**: The zone you are connected to (typically a city name) - - **Scope**: The flood scope configured by the regional admin for your zone - - **Channels**: Additional channels configured by the regional admin -- "Go Offline" / "Go Online" button to toggle offline mode while connected -- Disconnect button + - **Registered via**: How MeshMapper verified your device: **Mesh** (most trusted, your signed advert was heard over the mesh), **API** (trusted, registered with a signed advert through the MeshMapper API), or **Manual** (basic, added by an administrator). Tap it to open the **Registration Methods** explanation. Hidden in Offline Mode. +- **Regional Settings** (the header shows your zone name): + - **Scope**: The flood scope configured by the regional admin for your zone ("Global" if none) + - **Channels**: The channels the app listens on: always **Public** and **#wardriving**, plus any regional channels your admin added +- **Go Offline** / **Go Online** to toggle Offline Mode while connected +- **Disconnect** button For a detailed walkthrough of the connection process, see the [Connection Guide](app_connection_guide.md). @@ -302,8 +322,8 @@ For a detailed walkthrough of the connection process, see the [Connection Guide] ## Settings Tab -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). +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, API Endpoints, Apple Watch (iOS, once a watch has been paired), About & Support, and Developer Tools (hidden until you tap the version number on About & Support seven times). -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. +Some settings are locked while auto-ping is running to prevent mid-session changes that could affect data consistency. An amber banner reading "Some settings locked during auto-ping" appears at the top while they are locked. For a complete reference of every setting, see the [Settings Reference](app_settings_reference.md). diff --git a/docs/app_third_party_api.md b/docs/app_third_party_api.md index 26c7b1b..c34aa7f 100644 --- a/docs/app_third_party_api.md +++ b/docs/app_third_party_api.md @@ -1,6 +1,6 @@ # Custom API Endpoint - Third-Party Developer Guide -This document describes the API contract for receiving forwarded wardrive data from MeshMapper. When a user enables "Custom API Endpoint" in MeshMapper settings, every successful wardrive batch upload is also forwarded to your endpoint. +This document describes the API contract for receiving forwarded wardrive data from MeshMapper. When a user enables "Custom API Endpoint" in MeshMapper settings, every successful wardrive batch upload is also forwarded to your endpoint. This includes offline sessions the user uploads later: each 50-row chunk that uploads is forwarded as its own request. ## Request Format @@ -22,7 +22,7 @@ This document describes the API contract for receiving forwarded wardrive data f } ``` -The `data` array contains 1-50 ping objects per batch. Batches arrive approximately every 15-30 seconds during an active wardriving session. +The `data` array contains 1-50 ping objects per batch. During a live session the app uploads about 5 seconds after each TX, DISC, TRACE, DEFER or SCOPES item is queued, and on a 15-second timer otherwise (both stretch to 60 seconds on a constrained link such as satellite). Each successful upload is forwarded once. ## Ping Object Schema @@ -42,7 +42,7 @@ Every ping object contains a `type` field that determines which additional field | `radio_freq` | `string\|absent` | The radio configuration the item was recorded under, as `freqMHz,bwKHz,SF,CR` (e.g. `"910.525,62.5,7,5"`). Absent when the radio did not report its parameters. Present on every type, `DEFER` included. | | `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. | +| `iata` | `string\|absent` | MeshMapper zone code (e.g., `"RDU"`, `"MSP"`, `"YOW"`). The wardriver's current zone, or the last zone the app saved when there is no current one. On an offline session upload, it is the zone the upload was made from, for the whole chunk, not where each ping was recorded. | ### TX Ping (type: "TX") @@ -50,7 +50,11 @@ A transmitted ping broadcast on the wardriving channel, with repeater echo resul | Field | Type | Description | |-------|------|-------------| -| `heard_repeats` | `string` | Comma-separated repeater echoes: `"id(snr),id(snr)"` or `"None"` if no repeaters heard. IDs are hex strings (1-6 chars). SNR is in dB. | +| `heard_repeats` | `string` | Comma-separated repeater echoes: `"id(snr),id(snr)"` or `"None"` if no repeaters heard. IDs are upper-case hex: 2, 4 or 6 characters depending on the path's bytes per hop (8 is possible). SNR is in dB with two decimals, or `null` when the echo came through the user's own CARpeater (for example `"4E(null)"`). | +| `wire_tag` | `string` | The anonymous tag the ping carried on air (e.g., `"MM:Ab3dEf9hIj"`). | +| `ping_counter` | `integer` | The ping's number within the user's MeshMapper session. | + +Echoes that reached the user through more than one repeater are not in `heard_repeats`. They arrive as separate `RX` items at the TX ping's location. **Example:** @@ -62,10 +66,12 @@ A transmitted ping broadcast on the wardriving channel, with repeater echo resul "noisefloor": -103, "altitude": 84, "radio_freq": "910.525,62.5,7,5", - "heard_repeats": "4e(12.25),77(8.50)", + "heard_repeats": "4E(12.25),77(8.50)", "timestamp": 1768762843, "external_antenna": false, "power": "0.3w", + "ping_counter": 42, + "wire_tag": "MM:Ab3dEf9hIj", "contact": "D873B1F2", "iata": "YOW" } @@ -85,6 +91,8 @@ A transmitted ping broadcast on the wardriving channel, with repeater echo resul "timestamp": 1768762873, "external_antenna": false, "power": "0.3w", + "ping_counter": 43, + "wire_tag": "MM:Kl2mNo4pQr", "contact": "D873B1F2", "iata": "YOW" } @@ -92,11 +100,11 @@ A transmitted ping broadcast on the wardriving channel, with repeater echo resul ### RX Ping (type: "RX") -A passively observed mesh packet from a nearby repeater. +A passively observed mesh packet from a nearby repeater, or a TX echo that reached the user through more than one repeater. | Field | Type | Description | |-------|------|-------------| -| `heard_repeats` | `string` | Single repeater with SNR: `"id(snr)"` (e.g., `"4e(12.0)"`). | +| `heard_repeats` | `string` | Single repeater with SNR: `"id(snr)"` (e.g., `"4E(12.00)"`). Same ID and SNR format as TX, so the SNR can be `null` (`"4E(null)"`). | **Example:** @@ -106,7 +114,7 @@ A passively observed mesh packet from a nearby repeater. "lat": 45.26950, "lon": -75.77700, "noisefloor": -105, - "heard_repeats": "4e(12.00)", + "heard_repeats": "4E(12.00)", "timestamp": 1768762900, "external_antenna": false, "power": "0.3w", @@ -121,12 +129,14 @@ A response from a discovered repeater or room node. | Field | Type | Description | |-------|------|-------------| -| `repeater_id` | `string` | Hex ID of the discovered node (e.g., `"a3b2c1"`), or `"None"` for failed discovery. | +| `repeater_id` | `string` | Upper-case hex ID of the discovered node: the first 2, 4 or 6 characters of its public key, following the user's path bytes setting (e.g., `"A3B2C1"`). `"None"` for a failed discovery. | | `node_type` | `string` | Node type: `"REPEATER"` or `"ROOM"`. Absent on failed discovery. | -| `local_snr` | `number` | SNR measured locally (dB). | -| `local_rssi` | `integer` | RSSI measured locally (dBm, negative). | -| `remote_snr` | `number` | SNR reported by the remote node (dB). | -| `public_key` | `string` | Full 32-byte public key of the node (64 hex chars). | +| `local_snr` | `number` | SNR measured locally (dB). `0` if the stored value could not be read. | +| `local_rssi` | `integer` | RSSI measured locally (dBm, negative). `0` if the stored value could not be read. | +| `remote_snr` | `number` | SNR reported by the remote node (dB). `0` if the stored value could not be read. | +| `public_key` | `string` | Full 32-byte public key of the node (64 upper-case hex chars). | + +A failed discovery (no node answered) is only sent when the user or region has **Discovery Drop** on. It carries none of `node_type`, `local_snr`, `local_rssi`, `remote_snr` or `public_key`. **Example (successful discovery):** @@ -136,12 +146,12 @@ A response from a discovered repeater or room node. "lat": 45.26980, "lon": -75.77750, "noisefloor": -102, - "repeater_id": "a3b2c1", + "repeater_id": "A3B2C1", "node_type": "REPEATER", "local_snr": 11.75, "local_rssi": -85, "remote_snr": 9.50, - "public_key": "a3b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2", + "public_key": "A3B2C1D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0A1B2", "timestamp": 1768762950, "external_antenna": true, "power": "1.0w", @@ -174,9 +184,11 @@ A targeted zero-hop trace to a specific repeater. | Field | Type | Description | |-------|------|-------------| | `repeater_id` | `string` | Hex ID of the targeted repeater. | -| `local_snr` | `number` | SNR measured locally (dB). | -| `local_rssi` | `integer` | RSSI measured locally (dBm, negative). | -| `remote_snr` | `number` | SNR reported by the repeater (dB). | +| `local_snr` | `number\|null` | SNR measured locally (dB). | +| `local_rssi` | `integer\|null` | RSSI measured locally (dBm, negative). | +| `remote_snr` | `number\|null` | SNR reported by the repeater (dB). | + +Only traces the repeater answered are sent. **Example:** @@ -227,14 +239,14 @@ The `external_antenna`, `noisefloor`, `altitude` and `power` fields are not pres ### SCOPES (type: "SCOPES") -A repeater's answer to a direct scope discovery question, sent after a discovery finds the repeater. MeshMapper asks a discovered repeater which channels or contacts it passes, and the repeater answers with a list of scope names. +A repeater's answer to a direct scope discovery question, sent after a discovery finds the repeater. The app asks a discovered repeater which regions (flood scopes) it carries, and the repeater answers with a list of region names. A `SCOPES` item is only sent after the `DISC` item for the discovery that found the repeater. If the server stops offering scope discovery, queued `SCOPES` items are dropped and never forwarded. **A SCOPES answer is unverified.** MeshMapper checks each answer against a discovery the same radio reported and discards any it cannot confirm, but the batch answer does not say which were kept, and the app forwards the whole batch after the upload succeeds. A long answer can also be incomplete: the repeater leaves out names that do not fit in its reply. | Field | Type | Description | |-------|------|-------------| | `public_key` | `string` | Full 32-byte public key of the answering repeater (64 hex chars, upper case). | -| `scopes` | `array of string` | The scope names exactly as the repeater sent them, case-sensitive. `"*"` means the repeater passes unscoped traffic. May be empty. At most 33 entries. | +| `scopes` | `array of string` | The scope names exactly as the repeater sent them, case-sensitive. Each entry is `"*"` (the repeater passes unscoped traffic) or a name of 1 to 30 bytes that does not start with `#`. May be empty. At most 33 entries. | `lat` and `lon` are where the discovery that found the repeater was made, not where the answer arrived. `timestamp` is when the answer arrived. The `external_antenna`, `noisefloor`, `altitude` and `power` fields are not present on a `SCOPES` item. @@ -255,7 +267,7 @@ A repeater's answer to a direct scope discovery question, sent after a discovery ## 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. `SCOPES` items only appear from the app version that ships this feature, and only while scope discovery is on, either enforced by the region or switched on by the user, so your endpoint must accept batches with and without them too. 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. +A batch is whatever the app uploaded to MeshMapper in that round, so one request can mix every type above. `DEFER` items only appear 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. `SCOPES` items only appear while scope discovery is on, either enforced by the region or switched on by the user, so your endpoint must accept batches with and without them too. 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): @@ -269,10 +281,12 @@ A batch is whatever the app uploaded to MeshMapper in that round, so one request "noisefloor": -103, "altitude": 84, "radio_freq": "910.525,62.5,7,5", - "heard_repeats": "4e(12.25),77(8.50)", + "heard_repeats": "4E(12.25),77(8.50)", "timestamp": 1768762843, "external_antenna": false, "power": "0.3w", + "ping_counter": 42, + "wire_tag": "MM:Ab3dEf9hIj", "contact": "D873B1F2", "iata": "YOW" }, @@ -281,7 +295,7 @@ A batch is whatever the app uploaded to MeshMapper in that round, so one request "lat": 45.26950, "lon": -75.77700, "noisefloor": -105, - "heard_repeats": "4e(12.00)", + "heard_repeats": "4E(12.00)", "timestamp": 1768762900, "external_antenna": false, "power": "0.3w", @@ -334,14 +348,14 @@ Your endpoint should return any `2xx` HTTP status code on success. The response | `200-299` | Logged as success. No further action. | | `4xx` | Error logged to user's error tab (throttled to once per minute per status code). | | `5xx` | Error logged to user's error tab (throttled to once per minute per status code). | -| Timeout (>10s) | Error logged as timeout. | -| Network error | Error logged as network error. | +| Timeout (>10s) | Error logged as timeout (throttled to once per minute). | +| Network error | Error logged as network error (throttled to once per minute). | MeshMapper does **not** retry failed custom API requests. Each batch is sent exactly once. ## Configuration Link for End Users -As an endpoint operator, you can generate a configuration link that your users paste into their clipboard. In MeshMapper Settings > API Endpoints, they tap **Import from Clipboard** to auto-fill the URL and API key. +As an endpoint operator, you can generate a configuration link that your users copy to their clipboard. In MeshMapper Settings > API Endpoints, they switch on **Custom API Endpoint** (and accept the "Third-Party Data Sharing" notice), then tap **Import from Clipboard**, which only appears once the switch is on, to auto-fill the URL and API key. **Format:** @@ -352,13 +366,15 @@ meshmapper://custom-api?url=your-server.com/api/wardrive&key=your-api-key-here - `url` — Your endpoint host and path, **without** `https://` (MeshMapper prepends it automatically). - `key` — The API key the user should send. This will be set as their `X-API-Key` header value. +The link is read as an ordinary URL query, so percent-encode any `&`, `+`, `#` or `%` inside the `url` or `key` values (for example `&` as `%26`). Left unencoded, they cut the value short or change it. + **Example:** ``` meshmapper://custom-api?url=data.myproject.org/ingest/wardrive&key=sk_live_abc123def456 ``` -The user copies this link, opens MeshMapper Settings > API Endpoints, and taps "Import from Clipboard." Both fields are populated instantly. +The user copies this link, opens MeshMapper Settings > API Endpoints, and taps "Import from Clipboard." Both fields are populated instantly. The endpoint settings can't be changed while an auto mode is running. ## Security Notes @@ -370,7 +386,7 @@ The user copies this link, opens MeshMapper Settings > API Endpoints, and taps " ## Rate and Volume -- **Batch frequency**: Every 15-30 seconds during active wardriving (depends on auto-ping interval and batch timer). +- **Batch frequency**: About 5 seconds after each TX, DISC, TRACE, DEFER or SCOPES item, and every 15 seconds otherwise (60 seconds on a constrained link). Offline session uploads arrive as a burst of up to 50 items per request. - **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. diff --git a/docs/app_troubleshooting.md b/docs/app_troubleshooting.md index 9a83ce0..c8f9f1c 100644 --- a/docs/app_troubleshooting.md +++ b/docs/app_troubleshooting.md @@ -11,7 +11,8 @@ Common issues and how to resolve them. **Possible causes:** - Radio is not powered on or out of BLE range (typically 10-30m) -- Bluetooth is disabled on your phone +- Bluetooth is disabled on your phone (the Connect tab shows **Bluetooth is Off**) +- Location Services are off (the Connect tab shows **Location Services Disabled**) - Android: Location permission not granted (required for BLE scanning) - Another app/device is already connected (MeshCore only supports one BLE connection at a time) @@ -22,9 +23,11 @@ Common issues and how to resolve them. - Check Bluetooth and Location are enabled in system settings - Disconnect other apps connected to the device +If the Connect tab shows **Region Not Available** instead of a device list, you are outside every MeshMapper zone. See [Zone shows orange dash](#zone-shows-orange-dash-outside-coverage-area). + ### Connection fails at "Device Info" step -Retrieves your radio's public key (required for API auth). If this fails, the entire connection fails. +The step reads **Querying device info...** on screen. It retrieves your radio's public key (required for API auth). If this fails, the entire connection fails. **Causes:** Firmware compatibility issue or transient BLE error @@ -36,17 +39,21 @@ Retrieves your radio's public key (required for API auth). If this fails, the en ### Connection fails at "Session Acquisition" step -Authenticates with the MeshMapper API. +The step reads **Acquiring API slot...** on screen. It authenticates with the MeshMapper API. -**Causes:** +If MeshMapper can't be reached at all, the screen shows **Server Unreachable**: check your internet connection, try again, or use Offline Mode. Otherwise the app shows the server's reason: -- No internet connection -- MeshMapper API in maintenance mode - -**Solutions:** - -- Check internet connection -- Use Offline Mode during maintenance +| Message | What to do | +|---------|------------| +| "Unknown device. Please advertise yourself on the mesh using the official MeshCore app." | Send an advert from the MeshCore app so MeshMapper learns your radio, then try again | +| "App version outdated. Please update to the latest version." | Update the app | +| "Your phone's clock is out of sync. Turn on automatic date and time in your phone settings." | Turn on automatic date and time | +| "GPS signal is weak (need <50m). Waiting for a stronger signal..." | Wait for a better fix, or move somewhere with a clearer sky view | +| "Device clock error. Power-cycle your device to reset it." (or the server's own wording) | Power-cycle your radio | +| "Zone is at TX capacity. Only Passive mode works here." | Use Passive Mode, or try later | +| "This zone is currently disabled. Try again later." | Try later | +| "Rate limited. Please slow down." | Wait a moment before reconnecting | +| "Service is under maintenance. Try again later." | Use Offline Mode during maintenance | ### Bluetooth disconnects unexpectedly @@ -59,7 +66,7 @@ Authenticates with the MeshMapper API. **What happens:** -- Auto-reconnect up to **3 attempts** (3-second delay between each, 30-second overall timeout) +- Auto-reconnect up to **3 attempts** (3 seconds apart, 30-second overall limit) - Session, upload queue, and noise floor data are **preserved** - If auto-reconnect fails → full disconnect cleanup, manual reconnect needed @@ -80,24 +87,28 @@ Authenticates with the MeshMapper API. - Check location permission is granted for MeshMapper - Enable Location Services system-wide - Move to a location with clear sky view -- Android: If permanently denied, a snackbar appears with "Settings" button +- If the permission was permanently denied, a snackbar appears ("Location permission is disabled in system settings.") with a **Settings** button ### Zone shows orange dash (outside coverage area) - You are outside any registered MeshMapper zone -- Tap the zone chip to see nearest zone name and distance +- Tap the GPS chip to see the nearest zone's name and distance +- The Connect tab shows **Region Not Available**, with a **Request Region Onboarding** button - Travel to a registered zone, or use Offline Mode to wardrive in unregistered areas -### "GPS data is stale" warnings +### "Phone Clock Out of Sync" or "Weak GPS Signal" + +A zone check can fail in two related ways: -- Zone status queries need GPS < 60 seconds old and < 50m accuracy -- Regular pings only check the 25m movement requirement +- **Phone Clock Out of Sync**: your location looks out of date because your phone's clock is wrong. This is a time problem, not a GPS problem. Turn on automatic date and time (and time zone), then tap **Retry Zone Check**. +- **Weak GPS Signal**: zone checks need accuracy better than 50m. Move to improve accuracy, then tap **Retry Zone Check**. + +Pings themselves need accuracy of 100m or better, plus the minimum distance since your last ping. **Solutions:** -- Make sure GPS is actively tracking (not cached) -- Move to improve accuracy -- iOS: Enable Background Mode in Settings for continuous tracking +- Make sure GPS is actively tracking +- iOS: Turn on Background Location in Settings > General for continuous tracking --- @@ -105,18 +116,18 @@ Authenticates with the MeshMapper API. ### "Send Ping" button is disabled -Check these requirements: +A hint under the buttons explains most blocks. Check these requirements: -- **External antenna not set** — Choose Yes or No in Controls panel -- **Power level not set** — Device model was not recognized. Go to Settings to manually select your TX power level. -- **Not connected** — Need active Bluetooth connection -- **No GPS lock** — App needs valid GPS position -- **GPS accuracy too low** — GPS accuracy is too poor (> 100m). Move to a location with better reception. -- **Not in a zone** — Must be in a coverage zone (or use Offline Mode) -- **TX Disabled (Offline Mode)** — TX pings are not available in Offline Mode. Only discovery and passive RX work offline. -- **Zone Full** — All TX slots in your zone are taken. You can still use Passive Mode. -- **Controls locked** — Ping in progress (5s listening window or API upload) -- **Cooldown active** — Brief cooldown after a manual ping (15s) or after stopping Active/Hybrid Mode +- **External antenna not set** ("Select antenna option") — Choose Yes or No in the Controls panel +- **Power level not set** ("Select power level in Connect tab") — Device model was not recognized. Pick your power level in the Connect tab. +- **Not connected** — Need an active connection to your radio +- **No GPS lock** ("Waiting for GPS") — App needs a valid GPS position +- **GPS accuracy too low** ("GPS signal is weak") — Accuracy is worse than 100m. Move to a location with better reception. +- **Airborne** ("Airborne, wardriving blocked") — Wardriving from an aircraft is blocked +- **Passive only (Offline Mode)** — TX pings are not available in Offline Mode. Only discovery and passive RX work offline. +- **Passive only (zone full)** — All TX slots in your zone are taken, or the region allows no TX. You can still use Passive Mode. +- **Controls locked** — A ping is in progress (its 5-second listening window). The buttons do not wait for the upload. +- **Cooldown active** — Brief cooldown after a manual ping (15s) or after stopping Active/Hybrid Mode (5s) ### "No repeaters heard" on every ping @@ -137,7 +148,8 @@ Check these requirements: This is **normal behavior**: -- Pings skip when you haven't moved the minimum distance (default 25m) +- Pings are **Skipped** when you haven't moved the minimum distance (default 25m) +- Pings are **Deferred** by Smart Pinging when your square already has recent coverage. See [Smart Pinging](app_wardriving_modes.md#smart-pinging). - If "Auto-Stop After Idle" is enabled, auto-ping stops entirely after 30 minutes without movement --- @@ -154,14 +166,14 @@ If pings are missing from the map, check that the upload queue has cleared, the - Poor or no internet connection - API in maintenance mode -- API authentication expired **Solutions:** - Check internet connection -- Try "Force Upload" in Settings > Data > Queued Pings +- Tap the **Force upload** button (cloud icon) in Settings > Data > Queued Pings - Switch to Offline Mode during maintenance -- Disconnect and reconnect to refresh API session + +An expired session refreshes itself, so you don't need to reconnect for that. ### Data uploaded but not appearing on meshmapper.net @@ -177,38 +189,20 @@ If pings are missing from the map, check that the upload queue has cleared, the **Causes:** - Sound notifications disabled in Settings -- Phone on silent/vibrate mode +- The individual sound (Ping Sent, Response Received, Disconnect Alert) is switched off +- Phone media volume turned down - Another app has exclusive audio focus **Solutions:** -- Enable in Settings > General > Sound Notifications -- Check phone volume and ringer mode +- Enable in Settings > General > Sound Notifications, and check the three sounds under it +- Check phone media volume ### Audio hangs or freezes - App has a 3-second timeout protection -- On corruption, the app automatically resets and reloads audio assets -- If persists, toggle Sound Notifications off and on in Settings - ---- - -## Web-Specific Issues - -### "Web Bluetooth not supported" error - -- Web Bluetooth only works in **Chrome** and **Edge** -- Safari, Firefox, and other browsers are not supported - -### CORS errors during local development - -- Add the web security flag: `flutter run -d chrome --web-browser-flag="--disable-web-security"` - -### Web Bluetooth requires active tab - -- Unlike mobile, Web Bluetooth only works in the **foreground tab** -- Switching tabs or minimizing = Bluetooth connection lost -- No background mode for the web version +- On a timeout, the app automatically resets the audio session and reloads the sounds +- If it persists, toggle Sound Notifications off and on in Settings --- @@ -228,8 +222,8 @@ Logs include timestamped entries for BLE communication, GPS events, ping lifecyc ## Reporting Bugs 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 +2. Choose **Bug** (or **Feature**), add a short title, and describe the issue (what you expected vs what happened) +3. Optionally switch on **Include with feedback** and select which log files to include 4. Submit — a confirmation toast appears with a "View" link to track your report Also report issues on: diff --git a/docs/app_wardriving_modes.md b/docs/app_wardriving_modes.md index 102a916..7ac731e 100644 --- a/docs/app_wardriving_modes.md +++ b/docs/app_wardriving_modes.md @@ -2,6 +2,8 @@ MeshMapper offers four automated wardriving modes plus manual pinging. Each mode serves a different purpose, and choosing the right one depends on your goals and environment. +While a mode runs, its button turns green with an **Active** label underneath, and the button text counts down what happens next: **Next ping Ns**, **Next disc Ns**, **Listening Ns**, **Deferred Ns**, **Skipped Ns** or **Stopping Ns**. A small **Scopes** badge appears on the running Passive or Hybrid button while [Scope Discovery](app_settings_reference.md#scope-discovery) is asking repeaters for their scopes. + --- ## Manual Ping @@ -10,14 +12,14 @@ The simplest way to wardrive. Tap the **Send Ping** button on the Map tab to sen **What happens:** -1. The app checks GPS, zone, and that the 15-second manual cooldown has elapsed. No minimum distance requirement for manual pings. +1. The app checks that you have a TX slot, that your antenna and power level are set, that you have a GPS fix accurate to 100 m or better, that you are not airborne, and that the 15-second manual cooldown has passed. There is no minimum distance for manual pings. Whether you are inside a zone is checked by the server. 2. A short message is encrypted and sent as a channel message to #wardriving. This message **floods the entire mesh network**. If a **scope** is configured, it is scoped to that region instead. - - **By default, the message does not contain your GPS position** — it carries a short anonymous token, and your coordinates travel only to the MeshMapper server via the API. Anyone listening on the channel sees the token, not your location. (See [Broadcast My Coordinates](app_settings_reference.md#broadcast-my-coordinates) to opt in to on-air coordinates.) + - **By default, the message does not contain your GPS position.** It carries a short anonymous token, and your coordinates travel only to the MeshMapper server via the API. Anyone listening on the channel sees the token, not your location. (See [Broadcast My Coordinates](app_settings_reference.md#broadcast-my-coordinates) to opt in to on-air coordinates.) 3. The app listens for **5 seconds** for repeater echoes 4. Echoes are matched (decrypted and compared to what you sent) and logged as "heard repeats" 5. Ping and echo data are queued for upload -Controls lock during the 5-second window and API upload. +The controls unlock as soon as the 5-second window ends. The upload happens in the background. Send Ping itself then shows **Cooldown** until its 15 seconds are up. **When to use:** Quick testing, spot-checking a specific location, or occasional pings. @@ -29,7 +31,9 @@ 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. (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.) +**To start:** Tap the **Hybrid Mode** button in the Controls panel on the Map tab. Hybrid is on by default. If Hybrid Mode is switched off under Settings > Wardriving > Modes, this button shows as "Active Mode" instead. + +The button only appears while **Flood Traffic** is on. Flood Traffic is off on a fresh install, but the app turns it on each time you connect in a region that allows flood traffic. The button is also hidden while your zone is full (see [TX Capacity Limits](#tx-capacity-limits)). **What happens each interval (alternating):** @@ -43,9 +47,9 @@ Hybrid Mode is the **recommended default** for wardriving. It alternates between **Why Hybrid is the default:** 50% fewer channel messages than Active Mode while also collecting discovery data. Better for mesh health and more useful coverage data. -**Minimum distance:** Enforced between pings (configurable in Settings, default 25m). Pings pause when stationary. +**Minimum distance:** Enforced between pings (configurable in Settings, default 25m). Pings are skipped while you are stationary. -**Regional enforcement:** Enabled by default across all regions because we feel it provides the best balance between mesh load and data collected. Regional admins can disable Hybrid Mode for their zone via the admin portal if it doesn't suit their region. +**Regional enforcement:** A regional admin can require Hybrid Mode for a radio preset ("Enforce Hybrid", off by default). When it is enforced, the Hybrid Mode switch in Settings is locked on. !!! warning "Firmware requirement" The discovery half requires repeater firmware **1.10 or newer**. Repeaters on older firmware will not respond to discovery requests, but will still echo your channel messages normally. TX pings work with any firmware version. @@ -54,21 +58,21 @@ Hybrid Mode is the **recommended default** for wardriving. It alternates between ## Passive Mode -No channel messages (no mesh flooding at all). Sends **discovery requests** every 30 seconds and passively monitors mesh traffic. +No channel messages (no mesh flooding at all). Sends **discovery requests** every 30 seconds and listens to other mesh traffic. -**To start:** Tap the **Passive Mode** button (hearing icon) in the Controls panel. +**To start:** Tap the **Passive Mode** button (ear icon) in the Controls panel. **What happens:** -1. Every 30 seconds, sends a zero-hop discovery request (direct query, not a broadcast) +1. Every 30 seconds, sends a zero-hop discovery request (direct query, not a broadcast). Like the other auto modes, it skips the request if you have not moved your minimum ping distance, and defers it in squares with recent coverage ([Smart Pinging](#smart-pinging)). 2. Repeaters/rooms respond with node type, public key, and signal quality (local + remote SNR/RSSI) -3. Discovery Tracker collects responses during a 7-second window, deduplicates by public key, and filters carpeaters (RSSI stronger than -30 or by user-configured prefix value) -4. Unified RX Handler monitors for mesh traffic on subscribed channels -5. All discovery responses and RX observations queued for upload +3. Responses are collected for 7 seconds and deduplicated by public key. CARpeaters are filtered out: anything received at -30 dBm or stronger, your own CARpeater (matched by its full public key), and any CARpeater on your region's shared list. +4. The app also listens to other mesh traffic it hears (RX) +5. All discovery responses and RX observations are queued for upload **What it produces:** Discovery data (which repeaters are in direct range, bidirectional signal quality) and passive RX observations. -**When to use:** Map repeater locations without flooding the mesh. Also the only mode available when your zone is at TX capacity (see [TX Capacity Limits](#tx-capacity-limits)). +**When to use:** Map repeater locations without flooding the mesh. Also available when your zone is at TX capacity (see [TX Capacity Limits](#tx-capacity-limits)). !!! warning "Firmware requirement" Discovery requests require repeater firmware **1.10 or newer**. Repeaters on older firmware will not respond, so Passive Mode (and the discovery half of Hybrid Mode) will not detect them. @@ -78,16 +82,16 @@ 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 > Wardriving > 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, turn off Hybrid Mode in Settings > Wardriving > Modes (not possible where your region enforces Hybrid). Sends only channel messages (no discovery requests) at a regular interval (15, 30, or 60 seconds). **What happens each interval:** -1. Checks GPS freshness and minimum distance requirement +1. Checks your GPS fix and the minimum distance 2. If you haven't moved far enough (based on Settings, default 25m), the ping is skipped 3. Channel message sent (floods mesh or scoped) + 5-second echo listening window -4. Unified RX Handler monitors for passive mesh traffic +4. The app also listens to other mesh traffic it hears (RX) 5. All data (TX + RX) queued for upload **What it produces:** TX data (location, repeater echoes, SNR/RSSI) and passive RX observations. @@ -98,17 +102,18 @@ Sends only channel messages (no discovery requests) at a regular interval (15, 3 Targets a **specific repeater** by hex ID for focused signal testing. -**To start:** Tap the **Trace Mode** button (crosshair icon). Enter or select a repeater's hex ID. +**To start:** In the Trace row under the mode buttons (route icon), type the repeater's hex ID or tap the list button to choose it, then tap **Trace Mode**. The ID length follows your [Trace Bytes](app_settings_reference.md#trace-bytes) setting. **What happens each interval:** -1. Sends a zero-hop trace path command to the target repeater -2. Trace Tracker listens **5 seconds** for a response + +1. Sends a zero-hop trace path command to the target repeater, at your auto-ping interval. Traces are skipped until you have moved your minimum ping distance. +2. The app listens **5 seconds** for a response 3. If the repeater responds: logs RX SNR, RX RSSI, and remote (TX) SNR -4. Successful traces → posted to API. Failed traces → logged locally, shown as grey markers on noise floor graph. +4. Successful traces are uploaded. Failed traces are logged on the phone only, and show as grey markers on the noise floor graph. **What it produces:** Point-to-point signal quality over time and distance. -**When to use:** Antenna alignment, evaluating a specific repeater's coverage, diagnosing signal quality to a particular node. +**When to use:** Antenna alignment, evaluating a specific repeater's coverage, diagnosing signal quality to a particular node. Trace Mode also works when your zone is full or your region has turned flood traffic off. --- @@ -123,6 +128,8 @@ Smart Pinging holds back auto pings in squares that MeshMapper has already mappe 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. +Each deferral leaves a hollow circle on the map. You can hide these with **Show Deferred Markers** in Settings. + **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:** @@ -133,32 +140,31 @@ Smart Pinging holds back auto pings in squares that MeshMapper has already mappe - 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". + A ping that fails the minimum distance rule reads "Skipped" and is dropped. A deferred ping reads "Deferred" and is still owed. **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. +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 and the window is the region's. --- ## 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. +Regional admins set a **maximum number of active TX wardrivers** (slots) for each radio preset in their region. This prevents too many users from flooding the mesh at once. A preset the admin has not set up gets 0 slots, flood traffic turned off and a 60-second minimum interval. !!! note "Regions can disable flood traffic entirely" - Some regions disable flood (TX) wardriving traffic altogether. In those zones the Active/Hybrid/Send Ping controls are locked off (the **Flood Traffic** setting shows as set by the regional admin) and Passive and Trace modes are the available options. + Some regions disable flood (TX) wardriving traffic altogether. In those zones the **Flood Traffic** setting is locked off and shows as set by the regional admin, the Active/Hybrid and Send Ping buttons are hidden, and Passive and Trace modes are the available options. **When the zone is at capacity:** -- **Manual Ping, Hybrid Mode, and Active Mode are disabled** (they all send TX channel messages) -- **Passive Mode is the only option** (discovery requests don't flood the mesh) -- The app indicates TX is not allowed for your session +- **Send Ping and the Hybrid / Active Mode button are hidden** (they all send TX channel messages) +- **Passive Mode and Trace Mode still work** +- Tapping the zone chip in the Map tab's status bar explains that the zone is at capacity **To get a TX slot:** - Wait for another wardriver to disconnect and free up a slot -- New sessions will be granted TX access -- If already connected in Passive Mode, disconnect and reconnect to pick up a slot +- Slots are handed out when a session starts, so disconnect and reconnect to pick one up --- @@ -169,7 +175,7 @@ Regional admins set a **maximum number of active TX wardrivers** per zone (for e | General wardriving (driving/walking) | Hybrid Mode | | Mapping coverage in a new area | Hybrid Mode | | Finding nearby repeaters without mesh traffic | Passive Mode | -| Zone at TX capacity | Passive Mode (only option) | +| Zone at TX capacity | Passive Mode (or Trace Mode) | | Testing signal to a specific repeater | Trace Mode | | Quick spot-check at one location | Manual Ping | @@ -177,9 +183,9 @@ Regional admins set a **maximum number of active TX wardrivers** per zone (for e ## Stopping Auto-Ping -- Tap the active mode button again (shows as "running" with a pulsing animation) -- Brief cooldown after stopping Active or Hybrid Mode to prevent accidental toggling -- If "Auto-Stop After Idle" is enabled: auto-ping stops after **30 minutes** without GPS movement +- Tap the running mode button again (green, with **Active** under it). If a listening window is still open, the button reads **Stopping** until it ends. +- After stopping Active or Hybrid Mode there is a 5-second cooldown to prevent accidental toggling +- If "Auto-Stop After Idle" is enabled (the default): auto-ping stops after **30 minutes** without movement. Moving means leaving a 150 m circle around where you stopped, on 3 GPS fixes in a row. --- @@ -188,19 +194,19 @@ Regional admins set a **maximum number of active TX wardrivers** per zone (for e Regardless of mode, all data follows the same pipeline: 1. **Ping event** (TX, RX, DISC, or Trace) -2. **Logged in app** (Log tab + marker on Graph) -3. **Queued for upload** (persistent Hive-based queue) -4. **Batch uploaded** (up to 50 items, auto-flush every 15 seconds) +2. **Logged in app** (Log tab, and the noise floor graph in the History tab) +3. **Queued for upload** (a queue saved on the phone) +4. **Batch uploaded** (up to 50 items per batch). Pings are sent within about 5 seconds, other items about every 15 seconds. On a slow link, such as satellite, both stretch to 60 seconds. 5. **Appears on meshmapper.net** (community coverage map) !!! note - RX observations have an extra buffering step: grouped by repeater ID, flushed to upload queue when you move 25m or after 30 seconds, whichever comes first. + RX observations have an extra buffering step: grouped by repeater ID, flushed to the upload queue when you move 25m or after 30 seconds, whichever comes first. At most 4 RX observations per repeater go into each batch. --- ## Sound Notifications -If enabled (Settings > General > Sound Notifications): +Off by default. 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/assets/multiregion-duplicate-ids.svg b/docs/assets/multiregion-duplicate-ids.svg new file mode 100644 index 0000000..db99ced --- /dev/null +++ b/docs/assets/multiregion-duplicate-ids.svg @@ -0,0 +1,59 @@ + + Why duplicate repeater IDs need a multiregion group + A wardriver near the border of region AAA is repeated by region BBB's repeater AA. Not grouped: AAA only knows its own AA, so the ping is linked to the wrong repeater. Grouped as CCC: MeshMapper knows both AA repeaters, so the ping counts for coverage but is not linked to either. + + + + ✗ Not grouped + + + Region AAA + + Region BBB + + + + repeated + + + + linked here (wrong) + + + AA + + Wardriver + + AA + + AAA only knows its own AA, so the ping is linked to the wrong repeater. + + + + + ✓ Grouped as CCC + + + Multiregion CCC + + + Region AAA + + Region BBB + + + + + Duplicate + Duplicate + + + AA + + Wardriver + + AA + + CCC knows there are two AA repeaters, so the ping counts for coverage + but isn't linked to either one. + diff --git a/docs/assets/ping-types.svg b/docs/assets/ping-types.svg new file mode 100644 index 0000000..61e109b --- /dev/null +++ b/docs/assets/ping-types.svg @@ -0,0 +1,117 @@ + + How MeshMapper decides a ping's type + Each row shows your radio, a repeater, and an observer that feeds MeshMapper. BIDIR: your ping reached a repeater, you heard its repeat, and it reached an observer. DISC or TRACE: a repeater replied to your discovery or trace. TX: it reached an observer but you heard no repeat. RX: you heard mesh traffic without transmitting. DEAD: you heard a repeat but it never reached an observer. DROP: no repeat heard and it never reached an observer. + + + + + + Your radio + Repeater + Observer + (feeds MeshMapper) + + + + BIDIR + Repeat heard, and it reached + an observer + + + + + You + + AA + + Observer + + + + DISC / TRACE + A repeater replied to your + discovery or trace + + + + You + + AA + + Observer + + + + TX + Reached an observer, but + no repeat heard back + + + + + + + You + + AA + + Observer + + + + RX + Heard mesh traffic + without transmitting + + + You + + AA + + Observer + + + + DEAD + Repeat heard, but it never + reached an observer + + + + + + + You + + AA + + Observer + + + + DROP + No repeat heard, and it + never reached an observer + + + + + + + + + + + You + + AA + + Observer + + got through + + + + didn't get through + Colour bar = the square's colour on the map + diff --git a/docs/assets/region-boundaries-draw-polygon.png b/docs/assets/region-boundaries-draw-polygon.png deleted file mode 100644 index cd77060..0000000 Binary files a/docs/assets/region-boundaries-draw-polygon.png and /dev/null differ diff --git a/docs/assets/region-boundaries-edit-polygon.png b/docs/assets/region-boundaries-edit-polygon.png deleted file mode 100644 index bc3e573..0000000 Binary files a/docs/assets/region-boundaries-edit-polygon.png and /dev/null differ diff --git a/docs/assets/region-boundaries-editor-interface.png b/docs/assets/region-boundaries-editor-interface.png deleted file mode 100644 index 1328ea2..0000000 Binary files a/docs/assets/region-boundaries-editor-interface.png and /dev/null differ diff --git a/docs/assets/region-boundaries-hou1.png b/docs/assets/region-boundaries-hou1.png deleted file mode 100644 index 9e71182..0000000 Binary files a/docs/assets/region-boundaries-hou1.png and /dev/null differ diff --git a/docs/assets/region-boundaries-hou2.png b/docs/assets/region-boundaries-hou2.png deleted file mode 100644 index c9a5df9..0000000 Binary files a/docs/assets/region-boundaries-hou2.png and /dev/null differ diff --git a/docs/assets/region-boundaries-hou3.png b/docs/assets/region-boundaries-hou3.png deleted file mode 100644 index 4843c43..0000000 Binary files a/docs/assets/region-boundaries-hou3.png and /dev/null differ diff --git a/docs/assets/region-boundaries-hou4.png b/docs/assets/region-boundaries-hou4.png deleted file mode 100644 index 947a56f..0000000 Binary files a/docs/assets/region-boundaries-hou4.png and /dev/null differ diff --git a/docs/awards.md b/docs/awards.md index ebeb966..775da18 100644 --- a/docs/awards.md +++ b/docs/awards.md @@ -4,15 +4,20 @@ MeshMapper recognizes community contributors through a **Profiles & Awards** sys ### Viewing Profiles -You can view any users profile by clicking their name on a regional or [global leaderboard](https://meshmapper.net/global_leaderboard.php). Leaderboards also have a "Profiles" search button in the header, which allows you to search for any companion by name or ID. +You can view anyone's profile by clicking their name on a regional or [global leaderboard](https://meshmapper.net/global_leaderboard.php). Leaderboards also have a **Profiles** button in the header. Its search box lets you "Search by name or Public ID". + +The profile card shows **All Time**, **This Week**, **Grid Squares** and **First Pings** stats, along with any awards. + +- A device linked to a [My MeshMapper](portal.md) account shows the account's display name. +- A deleted device that nobody has claimed shows as "Orphaned device" and doesn't appear in search. ### Users -When a single person operates multiple companion devices in a region, that regions administrators can combine them into a **user group**. All devices in the group aggregate their points under a single primary companion. The group appears as one entry on the leaderboards, and the profile displays the combined statistics. +If you run more than one companion, link them all to your [My MeshMapper account](portal.md). They then show as one entry on the leaderboards, and your profile shows the combined totals. ### Manage Your Own Profile & Data -Wardrivers can now create an account on the [**My MeshMapper portal**](portal.md), link their companion devices, set the display name shown on leaderboards, and view or delete the data they have contributed. Additional profile features (avatar and bio self-management) are planned. +Wardrivers can create an account on the [**My MeshMapper portal**](portal.md), link their companion devices, set the display name shown on leaderboards, and view or delete their data. If you connect Discord, you can show your Discord avatar on leaderboards and your profile. Editing your own bio is not available yet. ## Awards @@ -25,25 +30,31 @@ These are granted automatically by the system based on wardriving milestones: | Award | Criteria | | --- | --- | | **Wardriver** | Any wardriving contribution (at least 1 data point) | -| **1,000 Data Points** | Accumulate 1,000 or more all-time points | -| **5,000 Data Points** | Accumulate 5,000 or more all-time points | -| **10,000 Data Points** | Accumulate 10,000 or more all-time points | -| **50,000 Data Points** | Accumulate 50,000 or more all-time points | -| **Ping Leader** | Rank #1 on a regional leaderboard | -| **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 | +| **1000 Data Points** | Accumulate 1,000 or more all-time points | +| **5000 Data Points** | Accumulate 5,000 or more all-time points | +| **10000 Data Points** | Accumulate 10,000 or more all-time points | +| **50000 Data Points** | Accumulate 50,000 or more all-time points | +| **Ping Leader** | Rank #1 on a regional leaderboard. Anonymous players are skipped, so it goes to the next real #1. | +| **Explorer 1** | Ping in 1,000 or more different grid squares | +| **Explorer 2** | Ping in 5,000 or more different grid squares | +| **Explorer 3** | Ping in 10,000 or more different grid squares | +| **Pioneer 1** | Be first to ping 500 or more grid squares | +| **Pioneer 2** | Be first to ping 1,000 or more grid squares | +| **Pioneer 3** | Be first to ping 2,500 or more 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) | +| **Global Leader** | Rank in the top 10 of a global leaderboard: All Time Legends, Top Wardrivers (7 Days), or Top Pioneers. | + +- Companions in [Anonymous Mode](app_connection_guide.md#anonymous-mode) can still earn milestone awards, but not Ping Leader or Global Leader. +- Awards are never removed automatically, so Ping Leader and Global Leader stay after you drop out of first place or the top 10. !!! info "Update Interval" - MeshMapper processes the aggregration of companion/user statistics, and auto assignment of awards, once every 24-hours. Check back later if you've earned an award but don't yet see it. + Stats and automatic awards update once a day. If you've earned an award but don't see it yet, check back tomorrow. ### Manual Awards -Master/Global Administrators can grant custom awards for special achievements, events, contest wins, donating to MeshMapper, or community contributions. +Master Administrators can grant custom awards for special achievements, events, contest wins, donating to MeshMapper, or community contributions. ## Available Awards @@ -102,7 +113,7 @@ function openAwardImage(src, name) { ## Request an Award or Suggest a New One -Use the form below to request a missing award or suggest a new award type for the community. +Use the form below to request a missing award or suggest a new award type for the community. Your name and details are always required. The Companion ID is only needed for award requests. Requests are sent to the MeshMapper team on Discord.
diff --git a/docs/backbone.md b/docs/backbone.md index 14da364..a8bdb96 100644 --- a/docs/backbone.md +++ b/docs/backbone.md @@ -1,6 +1,6 @@ # Backbone -The **Backbone** layer highlights the repeaters that carry most of a region's traffic. A repeater is a **backbone site** when it belongs to the smallest group of repeaters that, together, carry **half** of everything MeshMapper observed in the region over the last 7 days (the default; a region admin can change it). +The **Backbone** layer highlights the repeaters that carry most of a region's traffic. A repeater is a **backbone site** when it belongs to the smallest group of repeaters that, together, carry **half** of the traffic MeshMapper has observed on the region's links. This page explains what "traffic" means here, how each repeater's share is worked out, and why the numbers can move even when nothing changed on air. @@ -30,6 +30,12 @@ Several observers often hear the same packet. They log different paths, and thos This keeps the score about the mesh, not about where observers happen to be. Running three observers in one house doesn't triple the score of the repeater next door. +### How Long a Link Counts + +A link keeps adding points for as long as observers keep hearing it, so busy links build up over time. If no observer logs a link for **7 days**, it's dropped along with all its points. + +Region admins can change this with **Inferred, days** under **Neighbour links** in the admin panel (0 = never drop; set by the group admin for grouped regions). The same setting controls how long inferred lines stay on the Repeater Neighbours layer. + --- ## From Points to Shares @@ -38,7 +44,7 @@ Every link point is shared by the two repeaters at its ends, so each repeater co ### Worked Example -A small region with repeaters A, B, C, D and E, over one week: +A small region with repeaters A, B, C, D and E: | Packet | Heard by | Logged path | Links scored | |---|---|---|---| @@ -74,15 +80,17 @@ B alone has 44%, which is short. B + C have 69%, so **the backbone is B and C**. ## When a Hop Can't Be Identified -Each hop in a path is only the first 1, 2 or 3 bytes of a repeater's Public ID. MeshMapper only scores a link when **both** hops can be tied to exactly one known, placed repeater. +Each hop in a path is only the first 1, 2 or 3 bytes of a repeater's Public ID. MeshMapper only scores a link when **both** hops can be tied to exactly one known, placed repeater (see [The Rules](duplicaterepeaterid.md#the-rules)). ![Top: a 1-byte path 3A to 7F to C2 where two repeaters share 7F. Neither link scores, and no 3A-C2 shortcut is made. Bottom: the same route as 3A41 to 7F12 to C2E0 resolves, and both links score.](assets/backbone-chain-break.svg) - **1-byte collision.** In the path `3A → 7F → C2`, two repeaters in the region start with `7F`. MeshMapper can't tell which one relayed the packet, so neither `3A–7F` nor `7F–C2` scores. It also never invents a `3A–C2` link, because those two never heard each other directly. - **Multi-byte resolves it.** The same route as `3A41 → 7F12 → C2E0` scores both links, because only one repeater starts with `7F12`. -- **Unknown hop.** A hop that matches no placed repeater (never adverted, or no location set) breaks the chain the same way. +- **Unknown hop.** A hop that matches no placed repeater (never adverted, or no location set) breaks the chain the same way. So does a repeater that's **Disabled** or **Inactive**. - **Rescue by distance.** If exactly one of the colliding repeaters is within range of the hop next to it, MeshMapper uses that one. With the default 250 km range this rarely settles it inside a single region. -- **Too far apart.** Two hops more than 250 km apart (or the region's own limit) are treated as a misread path and don't score. +- **Different radio preset.** A link only counts if its radio preset matches both repeaters' current preset. +- **Same spot.** Two repeaters at exactly the same coordinates never score. +- **Too far apart.** Two hops more than 250 km apart are treated as a misread path and don't score. Region admins can change this limit with **Max link distance, km** under **Neighbour links** in the admin panel (set by the group admin for grouped regions). !!! tip "Multi-byte helps your score" Repeaters on 2- or 3-byte path hashes are credited far more reliably than 1-byte ones. Moving a repeater to multi-byte can raise its share without any change in real traffic. See [Multi-Byte Repeaters](multibyte.md). @@ -93,11 +101,12 @@ Each hop in a path is only the first 1, 2 or 3 bytes of a repeater's Public ID. Turn on the **Backbone** layer from the Layer Control. -- **Gold repeaters** are backbone sites. Only an **active** repeater turns gold. A stale or ambiguous repeater keeps its own colour even if it scores high, so importance never hides health. -- **The chip percentage** is that repeater's share of the region's traffic. -- **The repeater popup** shows **Traffic rank: #n of m** with its share, and marks backbone sites. +- **Gold repeaters** are backbone sites. Only an **active** repeater turns gold. A new, stale or ambiguous repeater keeps its own colour even if it scores high, so importance never hides health. +- **The chip percentage** is a backbone site's share of the region's traffic. Backbone chips show it even with the layer off. +- **The repeater popup** shows **Traffic rank: #n of m linked in region** with its share for any repeater that scores (`m` counts only repeaters with a scored link). Backbone sites also get a **Backbone Site** badge. +- **Turning the layer on** shows only backbone sites, and turns Repeater Neighbours and Repeater Scopes off. - **Backbone trunks** are the lines drawn between backbone sites. Each backbone site keeps its **3 busiest** links to other backbone sites. A trunk's colour is its rank among all trunks, busiest first. Line width has no meaning. -- On a **group** page, the whole group is scored as one pool, so a chip's share is its share of the whole page. +- On a **group** page, the whole group is scored as one pool, so a chip's share is its share of the whole page. A packet heard in two member regions is counted once in each, so links near a member border can score a little higher. --- @@ -107,18 +116,10 @@ A share is **relative**. Your percentage can drop while your repeater carries ex - **More traffic somewhere else.** A busy chat group on the other side of the region adds points to other links, and your slice of the total shrinks. - **An observer came or went.** A link only scores if some observer logs a path through it. A new observer downstream of your repeater makes more of its traffic visible, and losing one hides it. -- **A neighbour moved to multi-byte, or a new collision appeared.** Links around a hop can start or stop resolving. -- **Old traffic aged out.** The score only covers the last 7 days. +- **A neighbour moved to multi-byte, or a new collision appeared.** Links around a hop can start or stop resolving. A new collision drops the link and its points; if it clears, the link starts again from zero. +- **A link went quiet.** A link no observer has heard for 7 days is dropped, along with all its points. - **The backbone grew.** When traffic spreads over more links, it takes more repeaters to reach 50%, so each one's share is smaller. -!!! info "September 2026 changes" - Two changes in late September 2026 moved everyone's numbers: - - 1. **Every flood packet now counts.** Before, the backbone was built almost entirely from adverts and `#wardriving` messages. It now uses the path of every flood packet MeshMapper hears: direct messages, every channel, adverts and the rest. The pool is much larger and weighted toward where people chat. - 2. **Each packet counts once per link.** Before, a link scored once for every observer that logged it, which favoured repeaters near clusters of observers. - - The 7-day window still holds some traffic counted the old way. Expect movement until that ages out, about a week after the changes. - --- ## Frequently Asked Questions @@ -129,12 +130,12 @@ It means your repeater appears in more observed paths than most. That usually tr **Why is my repeater not gold when its share is high?** -Only **active** repeaters are drawn gold. A stale repeater, one that hasn't been heard recently, keeps its status colour even if it still scores. A repeater excluded for a duplicate ID doesn't score at all, because its hops can't be attributed. +Only **active** repeaters are drawn gold. A new repeater (first seen in the last 14 days) or a stale one (not heard recently) keeps its status colour even if it scores. A repeater excluded for a duplicate ID doesn't score at all, because its hops can't be attributed. -**Why does a repeater show 0%?** +**Why does a repeater have no share or traffic rank?** -No observer logged a path where it sits next to another identifiable repeater in the last 7 days. It may still be relaying traffic. It's either off the routes into observers, or its hops can't be resolved (often a 1-byte collision). +None of its links score. It may still be relaying traffic, but either no observer has logged a path where it sits next to another identifiable repeater, or its hops can't be resolved (often a 1-byte collision). See [When a Hop Can't Be Identified](#when-a-hop-cant-be-identified). **How often does it update?** -The server recalculates the backbone every time it processes new paths, currently about once an hour. +Link points are updated about once an hour. The map works out the backbone from those points each time you load the page. diff --git a/docs/botcommands.md b/docs/botcommands.md index 320cc1e..bf022af 100644 --- a/docs/botcommands.md +++ b/docs/botcommands.md @@ -1,10 +1,10 @@ # MeshMapper Bot Commands -The MeshMapper Discord bot responds to commands when tagged in a message. Commands can be issued using the `!` prefix or by asking in natural language — the bot will detect your intent automatically. +The MeshMapper Discord bot responds to commands starting with `!` and to questions when it's tagged. You can use a command, or ask in natural language and the bot will work out what you mean. For example, both of these work: -- `@MeshMapper !settings YOW` +- `!settings YOW` - `@MeshMapper what are the settings for YOW?` --- @@ -14,14 +14,14 @@ For example, both of these work: | Command | Description | | --- | --- | | `!help` | Displays a help message with information about the bot and some available commands. | -| `!status {IATA}` | Displays the status of a region. For pending regions, shows MQTT verification status. For active/inactive regions, shows data point, repeater, and observer counts. | -| `!settings {IATA}` | Displays the region's configuration settings including hop bytes, flood traffic, hybrid mode, stale repeater age, duplicate ID detection, and RX channels. | -| `!admins {IATA}` | Lists the administrators for a region along with their contact information. | -| `!bug {description}` | Submits a bug report to GitHub. Can also reply to a message to use its content as the description. The bot first asks you to confirm (react ✅) after checking the [Troubleshooting](troubleshooting.md) page. The bot uses AI to generate a concise title. Rate limited to 5 per user per hour. | +| `!status {IATA}` | Displays the status of a region (you can also use its name). For pending regions, shows MQTT verification status. For active/inactive regions, shows data point, repeater, and observer counts. | +| `!settings {IATA}` | Displays the region's settings: max wardriving sessions, flood traffic, enforce hybrid mode, min active/hybrid interval, stale repeater age, new repeaters enter pending, duplicate ID detection, failed DISC as DROP, hop bytes, and RX channels. | +| `!admins {IATA}` | Lists the administrators for a region. For contact details, use **Region Info** on the region's map. | +| `!bug {description}` | Submits a bug report to GitHub. Can also reply to a message to use its content as the description. The bot first asks you to confirm (react ✅) after checking the [Troubleshooting](troubleshooting.md) page. The confirmation times out after 2 minutes. The bot uses AI to generate a concise title. Rate limited to 5 per user per hour. | | `!issue {description}` | Alias for `!bug`. | | `!feature {description}` | Submits a feature request to GitHub. Works like `!bug` but creates a feature request instead (no confirmation step). | | `!resetpassword` | Points you to **Forgot password** on the MeshMapper portal. If you use Discord sign-in, no password is needed. The bot does not reset passwords or send credentials. | -| `!myissues` | Lists your bug reports and feature requests that were submitted through the bot and their current status. | +| `!myissues` | Lists up to 15 of your bug reports and feature requests submitted through the bot, with their status. Issues submitted through the website form aren't included. | !!! note "Additional Commands" Additional commands are available for users with the Developers or Moderator roles. These commands are not listed here. @@ -36,16 +36,16 @@ In addition to commands, you can tag the bot with any question about MeshMapper The bot can also be messaged directly (DM) without needing to tag it. -The bot's wiki knowledge refreshes automatically (it re-reads the wiki every few hours), so recently updated documentation makes its way into answers without any manual step. +The bot's wiki knowledge refreshes automatically (it re-reads the wiki every 4 hours), so recently updated documentation makes its way into answers without any manual step. ## Commenting on Issues -After submitting a bug report or feature request, anyone can add comments to the GitHub issue by simply replying to the bot's response message in Discord. The bot will automatically add your reply as a comment on the corresponding GitHub issue, with a link back to your Discord message. A ✅ reaction confirms the comment was added successfully. +After submitting a bug report or feature request, anyone can add comments to the GitHub issue by replying to the bot's message that contains the issue link. The bot will automatically add your reply as a comment on the corresponding GitHub issue, with a link back to your Discord message. A ✅ reaction confirms the comment was added; ❌ means it failed. -It works in the other direction too: when your issue is commented on, closed, reopened, or labelled on GitHub, the bot posts an update back into the original Discord thread — so you'll see progress on your report without leaving Discord. +It works in the other direction too: when your issue is commented on, labelled or closed on GitHub, the bot posts an update back into the original Discord thread — so you'll see progress on your report without leaving Discord. ## Notes -- All commands require the bot to be tagged (e.g. `@MeshMapper !status YOW`), except in DMs where tagging is not required. +- Commands starting with `!` work without tagging the bot. Natural-language requests and general questions need the bot to be tagged, except in DMs. - When submitting bugs or features by replying to a message, the "Submitted by" field credits the original poster, not the person who tagged the bot. - Replying to a bug or feature request does not require tagging the bot. diff --git a/docs/coverage-api.md b/docs/coverage-api.md index 7610bfc..f84d512 100644 --- a/docs/coverage-api.md +++ b/docs/coverage-api.md @@ -4,7 +4,7 @@ The Coverage API provides programmatic access to MeshMapper coverage grid-square ## Authentication -Access requires a **Coverage** API key. Each key is scoped to a specific region, a multiregion group, or a set of adjacent regions (see [Multi-Region Keys](#multi-region-keys)), and has a daily rate limit of 100 requests. +Access requires a **Coverage** API key. Each key is scoped to a specific region, a multiregion group, or a set of adjacent regions (see [Multi-Region Keys](#multi-region-keys)). Self-service keys have a daily limit of 100 requests; keys issued by the MeshMapper team may carry a different limit (the 429 body's `limit` field shows yours). ### Generating a Key @@ -33,6 +33,7 @@ GET https://meshmapper.net/coverage.php?key=YOUR_API_KEY | --- | --- | --- | | `key` | Yes | Your Coverage API key. | | `include` | No | Comma-separated list of optional sections to add to the response. Currently supports `repeaters` (e.g. `?include=repeaters`) — see [Repeater Fields](#repeater-fields). | +| `fresh` | No | `fresh=1` skips the 15-minute server cache and builds the grid now. Single-region and group keys only; multi-region and global keys return HTTP 400 `fresh_not_supported`. | | `f_*` | No | Filter the pings that go into the grid before it is built: by radio configuration, date, power or antenna. See [Filtering](#filtering). | ## Response Format @@ -114,12 +115,12 @@ GET https://meshmapper.net/coverage.php?key=YOUR_API_KEY | `fill_color` | string | Hex fill colour matching MeshMapper's map rendering. | | `border_color` | string | Hex border colour matching MeshMapper's map rendering. | | `snr` | float or null | Average signal-to-noise ratio (dB) across the cell's pings, if available. | -| `timestamp` | integer or null | Unix timestamp of the dominant (most recent, highest-priority) ping colouring this square. | +| `timestamp` | integer or null | Unix timestamp of the dominant (highest-priority, then newest) ping colouring this square, as stored (seconds; some older regions store milliseconds — values above 2e10 are milliseconds). | | `count` | integer | Number of pings aggregated into this cell — a confidence/density indicator. | | `snr_min` | float or null | Lowest SNR (dB) among the cell's pings. | | `snr_max` | float or null | Highest SNR (dB) among the cell's pings. | | `status_mask` | integer | Bitmask of **all** coverage types present in the cell (OR of `type_bits`). See [Cell Quality and Status Mask](#cell-quality-and-status-mask). | -| `first_seen` | integer or null | Unix timestamp of the **oldest** ping in the cell (`timestamp` is the newest/dominant). | +| `first_seen` | integer or null | Unix timestamp of the **oldest** ping in the cell, as stored (seconds; some older regions store milliseconds — values above 2e10 are milliseconds). | | `noise` | float or null | Average noise level (dB above the receiver's noise floor) across the cell's pings. | | `effective` | float | Average coverage-quality score for the cell, `0`–`3` (see below). | @@ -139,16 +140,17 @@ Returned in the top-level `repeaters` array **only** when the request includes ` ## Coverage Types -Each grid square's `coverage_type` is the **dominant** ping in that square — when multiple pings exist, the highest-priority type wins. +Each grid square's `coverage_type` is the **dominant** ping in that square — when multiple pings exist, the highest-priority ping wins (listed highest first below). Between pings of equal priority, the newest one wins. Pending pings (status 4) are left out entirely. -| Type | Colour | Priority | Description | +| Priority | Type | Colour | Description | | --- | --- | --- | --- | -| `BIDIR` | Green (`#1e7e34`) | 6 | Two-way confirmed link. | -| `DISC` | Cyan (`#17a2b8`) | 5 | Discovery or trace packet. | -| `TX` | Orange (`#fd7e14`) | 4 | Transmitted but not heard back. | -| `RX` | Purple (`#6f42c1`) | 3 | Heard traffic, without transmitting. | -| `DEAD` | Grey (`#6c757d`) | 2 | Repeater heard but no route. | -| `DROP` | Red (`#bd2130`) | 1 | No connection. | +| 1 (highest) | `BIDIR` with a heard repeat | Green (`#1e7e34`) | Two-way confirmed link. | +| 2 | `DISC` | Cyan (`#17a2b8`) | Discovery or trace packet. | +| 3 | `TX` | Orange (`#fd7e14`) | Transmitted but not heard back. | +| 4 | `RX` | Purple (`#6f42c1`) | Heard traffic, without transmitting. | +| 5 | `BIDIR` with no heard repeat | Green (`#1e7e34`) | Two-way link recorded, but no repeat heard. | +| 6 | `DEAD` | Grey (`#6c757d`) | Repeater heard but no route. | +| 7 (lowest) | `DROP` | Red (`#bd2130`) | No connection. | ## Cell Quality and Status Mask @@ -205,16 +207,16 @@ Single-region and group keys accept `f_*` query parameters that narrow which pin | Parameter | Value | Description | | --- | --- | --- | -| `f_radio_freq` | `906.875,250,10,5` | Exact radio configuration, the full `freqMHz,bwKHz,SF,CR` string as the app reports it. | +| `f_radio_freq` | `906.875,250,10,5` | Exact radio configuration, the full `freqMHz,bwKHz,SF,CR` string as the app reports it. Digits, dots and commas, up to 40 characters. | | `f_freq` | `906.875` | Frequency in MHz. Matches the whole frequency slot, so `906` does not match `906.875` and a kHz value such as `906875` matches nothing. | | `f_bw` | `62.5` | Bandwidth in kHz. | | `f_sf` | `7` | Spreading factor, 5 to 12. | | `f_cr` | `5` | Coding rate, 5 to 8 (4/5 to 4/8). | -| `f_days` | `30` | Only pings from the last N days. | +| `f_days` | `30` | Only pings from the last N days. 1 to 5 digits, at least 1. | | `f_dstart` | `1756684800000` | Only pings at or after this time, as a Unix timestamp in **milliseconds**. | | `f_dend` | `1757289600000` | Only pings at or before this time, milliseconds. | -| `f_power` | `20` | Transmit power, substring match against the reported value. | -| `f_extant` | `1` | Only pings reported with an external antenna. | +| `f_power` | `20` | Transmit power, substring match against the reported value. Letters, digits, dots, spaces and hyphens, up to 40 characters. | +| `f_extant` | `1` | Only pings reported with an external antenna. `f_extant=0` is the same as not sending it. | `f_freq`, `f_bw`, `f_sf` and `f_cr` can be given in any combination. Each one matches its own slot of the stored configuration exactly, so `f_freq=910.525&f_bw=62.5&f_sf=7` matches every coding rate on that channel: @@ -242,16 +244,17 @@ Things to know: - **A region that has never recorded a field returns an empty grid** for a filter on that field (zero squares, `point_count` 0) rather than the full set. - **Filtered responses are not cached server-side.** Every filtered request builds the grid from the region's pings, so it is slower than an unfiltered call and it counts against the daily quota like any other request. Keep filtered polling to the same 15 minute or longer cadence. - **Empty values are ignored.** `f_freq=` is the same as not sending it. -- **Anything else is an error.** An unknown `f_` parameter (a typo included) returns HTTP 400 `unsupported_filter`; a malformed value returns HTTP 400 `invalid_filter`. Both carry `param` naming the offending parameter and a `message` saying what was expected. The API never silently serves the full region in place of a filter it did not understand. +- **Anything else is an error.** An unknown `f_` parameter (a typo included) returns HTTP 400 `unsupported_filter`; a malformed value returns HTTP 400 `invalid_filter`. Both carry `param` naming the offending parameter and a `message` saying what was expected. The API never silently serves the full region in place of a filter it did not understand. These 400 errors still use up a request from your daily limit. +- **Filtering can be briefly unavailable.** If the server can't apply filters right now it returns HTTP 503 `filters_unavailable`; try again later. -Filters are not available on [multi-region](#multi-region-keys) or [global](#global-coverage-feed) keys, which return HTTP 400 `filters_not_supported`. +Filters are not available on [multi-region](#multi-region-keys) or [global](#global-coverage-feed) keys. Any `f_` parameter on those keys, even an empty one, returns HTTP 400 `filters_not_supported`. ## HTTP Caching and Compression The API is built for efficient, low-frequency polling. Coverage data does not change second-to-second, so please poll sparingly. -- **Compression.** Responses are gzip-compressed. Send `Accept-Encoding: gzip` (most HTTP clients do this automatically) to receive compressed data — payloads are roughly 9× smaller. -- **Server-side cache.** Responses carry `Cache-Control: public, max-age=900` and are cached for up to **15 minutes**. Polling more often than that returns identical data (and still counts toward your daily limit), so a poll interval of **15 minutes or longer is recommended**. `generated_at` tells you when the cached data was built. Filtered responses (see [Filtering](#filtering)) are built on every request and are not cached on the server. +- **Compression.** Responses are gzip-compressed. Send `Accept-Encoding: gzip` (most HTTP clients do this automatically) to receive compressed data — payloads are much smaller. +- **Server-side cache.** Responses carry `Cache-Control: public, max-age=900` and are cached for up to **15 minutes**. Polling more often than that returns identical data (and still counts toward your daily limit), so a poll interval of **15 minutes or longer is recommended**. `generated_at` tells you when the cached data was built. Filtered responses (see [Filtering](#filtering)) are built on every request and are not cached on the server. On single-region and group keys, `fresh=1` skips the cache and rebuilds now. - **Conditional requests.** Each response includes an `ETag` (and `Last-Modified`). Send the `ETag` value back in an `If-None-Match` header; if nothing has changed since, you'll get a **`304 Not Modified`** with an empty body, saving you the download. ```bash @@ -265,7 +268,7 @@ curl -s --compressed -H 'If-None-Match: "THE_ETAG_VALUE"' \ ## Rate Limits -Each API key has a **daily** request limit (100 requests). Counters reset daily. Every request that reaches your data — including cache hits and `304 Not Modified` responses — counts toward this limit. +Each API key has a **daily** request limit. Self-service keys get 100 requests a day; keys issued by the MeshMapper team may carry a different limit (the 429 body's `limit` field shows yours). Counters are reset by a daily job at midnight UTC. Every request that reaches your data — including cache hits and `304 Not Modified` responses — counts toward this limit. When you exceed your limit, the API returns HTTP 429: @@ -280,7 +283,9 @@ When you exceed your limit, the API returns HTTP 429: } ``` -A separate short-term, per-IP throttle protects against bursts; exceeding it also returns HTTP 429 (with `error: rate_limited`). Spacing requests out (see [Caching](#http-caching-and-compression)) avoids both. +`resets_in_hours` is counted from the last reset, so treat it as a rough guide; the actual reset happens at midnight UTC. + +A separate per-IP throttle protects against bursts: about 30 requests in a rolling window, then a 120-second lockout. Exceeding it returns HTTP 429 with `error: rate_limited` and no `Retry-After` header. Spacing requests out (see [Caching](#http-caching-and-compression)) avoids both. ## Error Responses @@ -290,12 +295,17 @@ A separate short-term, per-IP throttle protects against bursts; exceeding it als | 400 | `invalid_region` | Region code on key not found. | | 400 | `unsupported_filter` | An `f_` parameter that is not in the [Filtering](#filtering) table. `param` names it. | | 400 | `invalid_filter` | A filter value of the wrong shape (for example `f_sf=abc` or a seconds timestamp in `f_dstart`). `param` and `message` say what was expected. | -| 400 | `filters_not_supported` | An `f_` parameter on a multi-region or global key. | -| 401 | `invalid_key` | API key not found. | -| 403 | `no_region` | No region assigned to this key. | +| 400 | `filters_not_supported` | An `f_` parameter (even an empty one) on a multi-region or global key. | +| 400 | `fresh_not_supported` | `fresh=1` on a multi-region or global key. | +| 400 | `too_many_regions` | A multi-region key with more than 6 member regions. | +| 401 | `invalid_key` | API key not found, or not a Coverage key (message: `Invalid or non-Coverage API key`). | +| 403 | `no_region` | No region assigned to this key, or the key's region has been deleted. | | 429 | `rate_limit_exceeded` | Daily request limit reached. | | 429 | `rate_limited` | Too many requests in a short period (per-IP throttle). | | 500 | `server_error` | Internal error (database not found, etc.). | +| 503 | `filters_unavailable` | Filtering is temporarily unavailable. Try again later. | +| 503 | `rebuilding` | Global feed only: a rebuild is in progress and no cached copy exists yet. Sent with `Retry-After: 300`. | +| 507 | `over_memory_budget` | The data is too large to build in memory. Can happen on single regions as well as multi-region keys. | ## Managing Your Key @@ -305,7 +315,7 @@ If you have a Coverage API key assigned to your admin account, you can view your A Coverage key can be scoped to a **set of up to 6 regions** (for example `PDX,SEA,YVR`) instead of a single region. The response merges every member region's coverage into **one grid** — the same payload shape as a single-region response — so it suits integrations that render adjacent regions as one continuous map. -Multi-region keys are not self-service: like [global keys](#global-coverage-feed), they are issued by the MeshMapper team on request (the admin-panel self-service flow only creates single-region keys). Adjacent regions are the intended use — the merged grid serves them as one map. +Multi-region keys are not self-service: like [global keys](#global-coverage-feed) and keys with a custom limit, they are issued by the MeshMapper team (Master administrators) on request (the admin-panel self-service flow only creates single-region keys). Adjacent regions are the intended use — the merged grid serves them as one map. !!! info "Multi-region keys vs. Multiregion Groups" A [Multiregion Group](multiregions.md) merges regions *inside* MeshMapper — shared map, leaderboards, collision detection, and admin panel. A multi-region **key** changes nothing about the regions themselves; it only merges their coverage data in this API's response. If a group already exists, a key can simply be scoped to the group's code instead. A multi-region key is for sets of regions that aren't (and shouldn't become) a group. @@ -328,6 +338,7 @@ Identical to a single-region response — one merged `grid_squares` array, same "coverage_type_counts": { "BIDIR": 1620, "TX": 214, "RX": 1467, "DISC": 305, "DEAD": 41, "DROP": 455 }, "type_bits": { "BIDIR": 1, "TX": 2, "RX": 4, "DISC": 8, "DEAD": 16, "DROP": 32 }, "bbox": { "minLat": 45.301, "minLon": -123.212, "maxLat": 49.394, "maxLon": -121.751 }, + "radio_configs": { "906.875,250,10,5": 118400, "910.525,62.5,7,5": 13477 }, "grid_squares": [ "…same grid square objects as a single-region response, all members merged…" ], "regions": ["PDX", "SEA", "YVR"], "regions_skipped": 0 @@ -341,7 +352,7 @@ Note that `regions` and `regions_skipped` arrive **after** the `grid_squares` ar | `region` | string | The normalized member set as a CSV, uppercased and sorted (e.g. `"PDX,SEA,YVR"`). | | `region_name` | string | Member region names joined with `+`. | | `regions` | array | The member region codes, sorted — present only on multi-region responses. | -| `regions_skipped` | integer | Members that are registered but have no coverage data yet — present only on multi-region responses. | +| `regions_skipped` | integer | Members whose region database does not exist yet (skipped, never fatal) — present only on multi-region responses. | ### Differences from Single-Region Keys @@ -357,7 +368,7 @@ If a member region is later renamed, merged, or removed from MeshMapper, the key ### Caching and Limits -Caching, compression, conditional requests, and the daily quota work exactly as for single-region keys: 15-minute server cache, `ETag` / `If-None-Match` for `304 Not Modified`, gzip, and 100 requests per day (cache hits and 304s count). Response size scales with the number of member regions — poll at 15-minute intervals or longer. +Caching, compression, conditional requests, and the daily quota work exactly as for single-region keys: 15-minute server cache, `ETag` / `If-None-Match` for `304 Not Modified`, gzip, and the key's daily limit (cache hits and 304s count). Response size scales with the number of member regions — poll at 15-minute intervals or longer. ## Global Coverage Feed @@ -405,7 +416,7 @@ Instead of a single region's payload, a global key returns an envelope containin | `region_count` | integer | Number of sections in `regions`. Note this field arrives **after** the `regions` array — use a standard JSON parser rather than assuming key order. | | `regions_skipped` | integer | Regions omitted because they have no coverage data yet. | -`?include=repeaters` works exactly as for regional keys, adding a `repeaters` array to each section. Sections do not carry `radio_configs` or `filters`; those belong to single-region and group responses. +`?include=repeaters` works exactly as for regional keys, adding a `repeaters` array to each section. Sections do not carry `radio_configs` or `filters`. `radio_configs` belongs to single-region, group and multi-region responses; `filters` only to filtered single-region and group responses. ### Response Size and Pagination @@ -423,7 +434,7 @@ The global response aggregates the entire fleet, so it is cached more aggressive - The server cache lasts **6 hours** (`Cache-Control: public, max-age=21600`). Polling more often returns identical data; **once or twice a day is the intended usage**. - A request that arrives after the cache has expired triggers a rebuild. The response **streams region-by-region while it builds** — data starts flowing immediately, but the complete download can take a minute. Configure a generous *total* timeout in your HTTP client (the connection is never idle, so per-read timeouts are fine at their defaults). All other requests are served instantly from cache. -- `ETag` / `If-None-Match` conditional requests work exactly as for regional keys, and a `304 Not Modified` is by far the cheapest way to poll. +- `ETag` / `If-None-Match` conditional requests work exactly as for regional keys, and a `304 Not Modified` is by far the cheapest way to poll. The response that triggers a rebuild carries no `ETag`; the next (cached) response does. ### Differences from Regional Keys @@ -431,4 +442,4 @@ The global response aggregates the entire fleet, so it is cached more aggressive | --- | --- | | `fresh=1` | HTTP 400, `fresh_not_supported` — global rebuilds are cache-driven only. | | `f_*` filter parameters | HTTP 400, `filters_not_supported`. | -| Rebuild already in progress elsewhere | Served the previous cached copy; if no cached copy exists yet, HTTP 503 with `error: rebuilding` and a `Retry-After` header — retry after the indicated delay. | +| Rebuild already in progress elsewhere | Served the previous cached copy; if no cached copy exists yet, HTTP 503 with `error: rebuilding` and `Retry-After: 300` — retry after the indicated delay. | diff --git a/docs/dataupload.md b/docs/dataupload.md index d283602..eec3946 100644 --- a/docs/dataupload.md +++ b/docs/dataupload.md @@ -3,7 +3,11 @@ MeshMapper allows for the upload of legacy coverage data via CSV upload. This feature is designed to import data collected from other systems. !!! warning "Administrator Only" - Due to the complexity of maintaining data integrity, only a MeshMapper Master or Global Administratorcan upload legacy data. [Please reach out to start this process](https://wiki.meshmapper.net/administratorlist/). + Due to the complexity of maintaining data integrity, only a MeshMapper Master or Global Administrator can upload legacy data. [Please reach out to start this process](administratorlist.md). + +Uploads are done in the Master Admin panel, on the **Legacy Upload** tab, using the **Legacy Data Upload** card: pick the region, choose the CSV file, map the columns, and use **+ Add Field** for any extra columns. + +Each upload goes to one region and **replaces all existing legacy data** for that region. Group maps show their members' legacy data combined. ## CSV Requirements @@ -11,12 +15,14 @@ The uploaded file must be in **CSV** format and contain, at a minimum, the follo * **Latitude** * **Longitude** -* **Time** - Unix timestamp +* **Time** - Unix timestamp in seconds or milliseconds, or a standard date string. * **Status** - See definitions below -A **Coverage Radius** can also be set, which can expand each coverage point beyond the default grid size (300m x 300m). +The header names are mapped on the upload form (defaults `lat`, `lon`, `status`, `date`). + +You may also include additional columns (e.g. `Repeater`, `RSSI`, `SNR`); each needs a display name. They are stored in the region's legacy database but are not currently shown on the map. -You may also include any number of additional columns (e.g., `Repeater`, `RSSI`, `SNR`), which will be stored and available for display. +Separately from the CSV, a per-region **Grid Expansion** setting (radius in squares, 0–20, default 1) sets how far each legacy point spreads in Detailed grid mode: 0 = one ~100 m square, 1 = 3×3 (~300 m), 6 = 13×13 (~1.2 km). In Simplified mode each point fills a single 300 m square. ### Status Definitions @@ -30,11 +36,15 @@ The `status` column should contain an integer representing the coverage type, co | **3** | **DEAD** | **Grey** | **Dead** - Repeater heard the ping, but it did not make it into the wider mesh. | | **5** | **RX** | **Purple** | **Receive** - Heard traffic while in RX mode. | | **6** | **DISC** | **Cyan** | **Discovery** - Discovery packet sent and reply heard. | -| **7** | **TRACE** | **Cyan** | **Trace** - Targeted trace request sent and reply heard from a specific repeater. | +| **7** | **TRACE** | **Cyan** | **Trace** - Targeted trace request sent and reply heard from a specific repeater. Shown the same as DISC. | + +Any other status value is drawn red. ## Visualization & Limitations -Legacy data appears on its own layer on the map. +Legacy data appears on its own map layer, called **Legacy Data**. Legacy squares are never drawn where regular coverage exists. + +The **Manage Legacy Databases** card on the same tab lists each region's legacy data, with a **Delete** button. Unlike standard MeshMapper data, legacy uploads have the following limitations: diff --git a/docs/duplicaterepeaterid.md b/docs/duplicaterepeaterid.md index 98f88fa..ce73493 100755 --- a/docs/duplicaterepeaterid.md +++ b/docs/duplicaterepeaterid.md @@ -1,128 +1,104 @@ -!!! success "Multi-Byte Hops Are Here!" - MeshCore firmware now supports multi-byte repeater hop identification (up to 3 bytes), and MeshMapper fully supports it. Regions running firmware with 2 or 3 byte hops will see far fewer (or zero) collisions. This requires repeaters and companions running **firmware version 1.14.0 or newer**. - - For regions still running 1-byte hops, duplicate repeater IDs can be managed using the below methods, or by driving in **Hybrid** mode where **Discovery** packets are used. **Discovery**, or **DISC**, packets associate with repeaters using their full Public ID. [Read more about this here.](#workarounds) - # Duplicate Repeater IDs -As a regions mesh network grows, the likelihood of two repeaters sharing the same short identifier increases. MeshMapper has a robust system for detecting, handling, and resolving these "collisions" to ensure data integrity. - -MeshMapper does not filter out repeaters outside of a regions defined boundry, as that would not be an accurate representation of real-world RF conditions. - -!!! tip "Override Available" - Regions now have the ability to override MeshMapper's default duplicate ID detection logic if they prefer to visualize all data regardless of ambiguity. +Packets identify each repeater they pass through by a short **hop ID**: the first 1, 2 or 3 bytes of its Public ID. As a region grows, two repeaters can end up with the same hop ID. This is a **collision**, and MeshMapper can't always tell which of the two a packet went through. - [Learn how to override duplicate detection](https://wiki.meshmapper.net/overrideduplicates/) +This page explains how MeshMapper decides, what you'll see, and how to fix it. -## Hop Bytes: 1, 2, or 3 +!!! tip "The best fix is multi-byte" + With 1-byte IDs there are only 254 to go around, so collisions are common. With 2 or 3 bytes they become rare. See [Multi-Byte Repeaters](multibyte.md) to upgrade. -MeshCore repeaters are identified in packets by appending a portion of their Public ID as a "hop" to each message they relay. The number of bytes used for this identifier is called **Hop Bytes**, and is configurable per-region in MeshMapper. +## The Rules -| Hop Bytes | Hex Characters | Unique IDs | Example | -| --- | --- | --- | --- | -| **1** | 2 | ~254 | `A1` | -| **2** | 4 | ~65,536 | `A1B2` | -| **3** | 6 | ~16,777,216 | `A1B2C3` | +MeshMapper follows two rules, on the server and on the map. -Region administrators can configure the Hop Bytes setting in the admin panel under **Settings**. This should match the firmware configuration of the repeaters in the region. +### Rule A: When a Repeater Is Ambiguous -!!! info "Per-Repeater Detection" - MeshMapper tracks hop bytes on a per-repeater basis. If a repeater sends in a ping using a longer ID than previously seen, MeshMapper automatically updates that repeater's hop bytes value. This means a region transitioning from 1-byte to 2-byte hops will see repeaters update as they are heard. +A repeater is marked **Ambiguous** if it **can't be told apart from another repeater at its own width**: -### The 1-Byte Limitation + - A 1-byte repeater is judged on its first byte. + - A multi-byte repeater is judged at the width it advertises (at least 2 bytes). -In **1-byte mode**, repeaters are identified using the first two characters of their Public ID (e.g., `A1`, `4F`, `09`). Since this is only two hexadecimal digits long, there are only **254 possible combinations** (01 to FE...00 and FF are reserved in the MeshCore firmware). As the number of repeaters in a region increases, it becomes statistically inevitable that two completely different devices will end up with the same Short ID. +This is judged separately for each repeater, so a collision doesn't always flag both: -When this happens, it is called a **Collision**. +| Repeaters | Result | +| --- | --- | +| `AB` (1-byte) and `AB` (1-byte) | **Both Ambiguous.** They can't be told apart. | +| `AB` (1-byte) and `AB12` (2-byte) | **Only `AB` is Ambiguous.** A 1-byte `AB` hop could be either, but `AB12` is unique at its own width. | +| `AB12` (2-byte) and `AB9F` (2-byte) | **Neither.** They're different at 2 bytes. | -With **2-byte** or **3-byte** hops, the number of available unique IDs increases dramatically, making collisions extremely unlikely in all but the largest deployments. +### Rule B: When a Ping's Hop Is Credited -## How MeshMapper Handles Collisions +A hop in a ping's path is credited to a repeater only if **exactly one** repeater's ID starts with that hop, at the hop's own width. -MeshMapper prioritizes data accuracy. If two repeaters share the same short ID prefix (at the configured hop byte length), and a message repeat is heard by or is received via that prefix, the system has no way of knowing *which* physical repeater was actually involved. To prevent potentially inaccurate data from being represented on the map, MeshMapper enters a "Quarantine" mode for the affected devices. + - **One match**: credited to that repeater. + - **More than one**: ambiguous. The ping still counts for coverage, but isn't linked to any repeater. + - **No match**: unknown. The ping still counts, unlinked. -### Smart Collision Detection +### Other Rules -MeshMapper uses **per-repeater hop bytes** to determine whether two repeaters are truly in collision: + - **Discovery (DISC) pings** carry the repeater's full Public ID, so they're always credited to the right repeater, even during a collision. **TRACE** pings only carry the short hop ID, so Rule B applies to them. + - **Corrupted adverts**: a garbled advert that makes a near-copy of a repeater's ID is recognised as the same repeater and doesn't make it Ambiguous. + - **Far-away matches**: if the only match is unusually far from the ping, it's held for a region admin to review instead of being linked. + - **Groups**: in a [multiregion group](multiregions.md), collisions are checked across every region in the group. + - **Outside the boundary**: repeaters outside a region's boundary are still counted (tagged **Out of Region**), because RF doesn't stop at the border. -- Two repeaters are only considered colliding if they are **indistinguishable** at the longer of their two hop byte lengths. -- For example, repeater `AB` (1-byte) and repeater `AB12` (2-byte) are **not** in collision, because at 2 bytes (`AB` vs `AB12`), they are distinguishable. -- However, repeater `AB` (1-byte) and repeater `AB` (1-byte) with different full Public IDs **are** in collision, because at 1 byte they cannot be told apart. +## What You'll See -This means regions transitioning from 1-byte to 2-byte firmware will see collisions automatically resolve as repeaters begin reporting longer IDs. + - **On the map**: the repeater's chip has a **red** edge (**Ambiguous** in the Legend). + - **In its details**: an **Ambiguous** status and a red **AMBIGUOUS ID DETECTED** box listing its **Collision Group**. + - **On a ping**: when you select a single ping with an ambiguous hop, red dashed **Duplicate** lines go to each possible repeater with their distance, so you can judge which was likely involved. + - **On leaderboards**: Ambiguous repeaters stay listed, marked with a red **\*** ("Ambiguous ID"). Pings where their hop was ambiguous don't count towards them. + - **For admins**: an **Ambiguous Public IDs Detected** box in the admin panel, plus an optional Discord DM and region webhook (both called **Ambiguous Repeater ID**). -### 1. Detection & Quarantine -When a new repeater appears on the network with an ID that is indistinguishable from an existing device (at their respective hop byte lengths): +## What Happens to the Data - - **Both** repeaters (the existing one and the new one) are immediately flagged as **Excluded**. - - The system assigns the new repeater a temporary internal ID (e.g., `X1`) to differentiate it in the database and map, but it remains linked to the collision. - - Both repeaters are excluded from regional or global leaderboards and statistics (like maximum distance reached) +A ping whose hop was ambiguous is stored as unlinked, and **stays unlinked**, even after the collision is resolved. MeshMapper won't guess later. -### 2. Map Appearance +When a new repeater creates a collision, MeshMapper also checks recent pings that were linked to the old repeater before the collision existed. Any that could now belong to either repeater are unlinked. - - **Red Chips**: Both repeaters will appear on the map with a **Red** edge on their chip (instead of the usual Green, Pink or Grey). The map legend calls this state **Ambiguous ID**. - - **Popups**: Clicking on the repeater will show its status as "Duplicate" and will list the repeaters that are in collision with it. - - **Pings**: Clicking a grid square on the map that has a repeater involved in an active collision will draw red lines to each repeater in the collision group (and list distance), allowing the viewer to make their own assumption on which repeater was actually involved. - - **Leaderboards**: Both repeaters are immediately removed from all Leaderboards (Best Repeaters, Max Range, etc.) both on the local region and globally to prevent skewed statistics. +## Avoiding Collisions -### 3. Impact on Collected Data +### Upgrade to Multi-Byte - - **Ambiguity**: If a ping is ingested containing a repeater that has a collision (e.g., via `A1`), MeshMapper cannot attribute that hop to a specific location with certainty. - - **Data Integrity**: This data is forever flagged as being ambiguous, and will never associate with a repeater (even after the collision is resolved). +The most effective fix. Once repeaters advertise 2 or 3 bytes, most collisions clear up on their own. See [Multi-Byte Repeaters](multibyte.md). -## Workarounds +### Wardrive in Hybrid Mode -### Upgrade to Multi-Byte Hops -The most effective solution is to upgrade your region's repeaters to firmware that supports **2-byte or 3-byte hops**. Once upgraded, update the **Hop Bytes** setting in your region's admin panel to match. As repeaters are heard with longer IDs, MeshMapper will automatically update their hop byte tracking and resolve false collisions. +**Hybrid** mode sends **Discovery (DISC)** requests: "who's out there?" Any repeater in range (firmware 1.10+) replies with its full Public ID, so the ping is credited correctly even when its short ID collides. -### Hybrid Wardriving Mode -Wardrivers are encouraged to collect data in **Hybrid** mode, which utilizes **Discovery**, or **DISC**, packets. You can think of these packets as broadcasting "Hello, who's out there?", and any repeater within hearing distance (and with compatible firmware - 1.10+) will respond with their full Public ID. As we're not relying on only the short hop ID to make the association to the repeater, associations can be made even if the short ID of that particular repeater is in collision with another. +!!! tip "Enforce Hybrid" + Region admins can require Hybrid mode for a radio preset with the **Hybrid** column under **Settings → Wardriving → Radio Channels** in the admin panel. Wardrivers on that preset can't use Active mode. -!!! tip "Enforce Hybrid Mode" - If a region is large and contains many duplicate ID's, region administrators can choose to "Enforce Hybrid Mode" for their region. This will prevent any **Active** wardriving from occuring in the region by automatically enabling Hybrid mode for wardrivers. The option is available in the regional admin panel. - -## Resolution - -Collisions are typically resolved in one of two ways: +## Resolving a Collision ### Automatic Cleanup -Often a collision happens because an old, offline repeater is still in the database when a new one comes online. That resolves itself without any admin action. - - MeshMapper runs a cleanup routine every day. - - A colliding repeater that hasn't been heard for the region's **Repeater Inactive After** window (default 30 days) is marked **Inactive** and drops off the map. - - **The Survivor**: an Inactive repeater no longer counts as a competing claim on that ID, so the remaining repeater is restored to **Active** on its next advert. Its icon returns to normal, it reappears on leaderboards, and new pings associate with it properly again. +Often a collision is an old, offline repeater still on record when a new one comes online. That fixes itself: -Neither repeater is deleted. If the silent one comes back on air, it is reactivated — and if the ID is still ambiguous, both are excluded again. + - Every day, a repeater that hasn't been heard for the region's **Repeater Inactive After (Days)** (default 30, under **Settings → Repeaters, Neighbours & Scopes**) is marked **Inactive** and drops off the map. + - Inactive repeaters don't count in collisions, so the remaining repeater returns to normal on the next advert in that ID range. + - If the silent repeater comes back on air, it's reactivated, and if the ID still collides, it's Ambiguous again. + +Inactive repeaters aren't deleted unless the region has set a retention period for removing them. !!! tip "Bypass Auto Delete" - If a repeater is known to go offline for extended periods (seasonal deployment, remote location, etc.), administrators can enable **Bypass Auto Delete** on that repeater via the edit modal. This keeps it out of every automatic routine, including the inactive marking above — which also means it will keep its colliding partner excluded while it's away. + For a repeater that goes offline for long periods (seasonal, remote), admins can tick **Bypass Auto Delete** in its edit window. Automatic cleanup then skips it. It also keeps its partner Ambiguous while it's away. ### Manual Resolution -If both repeaters are active and legitimate (a true collision between two live devices): - - - Region administrators receive an alert regarding the collision. If able, it is suggested that the administrator resolve the issue by asking the owner of the new repeater to generate a new ID. - - If the administrator knows the the collision has been cleared, they may manually reinstate the remaining repeater and delete the old. If the collision has not been cleared, both repeaters will enter excluded state again on next advert. -!!! warning "Note" - As long as two (or more) repeaters are indistinguishable at their hop byte length, regardless of current status, pings will not get associated to a repeater with that ID, unless those pings are of **DISC** type (which associate using the full Public ID of the repeater). +If both repeaters are live and genuine: -!!! info "TRACE vs DISC for Collisions" - Unlike **DISC** packets which use the full Public ID to uniquely associate with a repeater, **TRACE** packets only carry the short repeater hop ID. This means TRACE data is subject to the same prefix-based collision detection as standard BIDIR/TX/DEAD pings. In regions with active duplicate IDs, TRACE data for those repeaters will be quarantined just like other ping types. + - The best fix is to ask one owner to **generate a new ID** for their repeater, or to upgrade both to multi-byte. + - If one repeater is gone for good, a region admin can set its **Status** to **Inactive** or **Disabled** in the admin panel. The other returns to normal on the next advert. + - Setting an Ambiguous repeater back to **Active** doesn't stick. It's re-checked on the next advert. -## Summary Table +!!! warning "Deleting doesn't help" + A deleted repeater adds itself back on its next advert. Change its status instead. -| State | Indicator | Meaning | -| --- | --- | --- | -| **Active** | Green Chip Edge | Normal operation. Unique ID. | -| **New** | Pink Chip Edge | Recently discovered (less than 14 days old). | -| **Excluded** (shown on the map as **Ambiguous ID**) | **Red Chip Edge** | **Duplicate ID Detected.** Data from this repeater is currently untrusted. | +## Turning Detection Off -## Multi-Byte Hop Support +A region can turn this off with **Disable Duplicate ID Detection Logic**, and show every possible repeater instead. See [Override Duplicate IDs](overrideduplicates.md). -MeshCore now supports multi-byte repeater hop identification, available in **firmware version 1.14.0 and newer** for both repeaters and companions. MeshMapper fully supports **1-byte**, **2-byte**, and **3-byte** hop modes across all features including collision detection, coverage mapping, leaderboards, etc. +## Repeater States -| Hop Bytes | Max Unique IDs | Suitable For | -| --- | --- | --- | -| **1 byte** | ~254 | Small regions with few repeaters | -| **2 bytes** | ~65,536 | Most regions | -| **3 bytes** | ~16,777,216 | Very large deployments | +For every repeater state and colour (Active, New, Stale, Ambiguous, Backbone), see [Repeater States](visuals.md#repeater-states). diff --git a/docs/embedding.md b/docs/embedding.md index 09fb1d5..8c17824 100644 --- a/docs/embedding.md +++ b/docs/embedding.md @@ -56,16 +56,17 @@ Toggle layers on or off with `1` (show) or `0` (hide). | `drop_grid` | Dead coverage (grey) | `1` (on) | | `fail_grid` | Dropped packets (red) | `0` (off) | | `repeaters` | Repeater markers | `1` (on) | -| `rep_coverage` | Repeater coverage lines | `0` (off) | +| `rep_coverage` | Repeater max-range circles | `0` (off) | | `grid_lines` | Grid outline lines | `0` (off) | ### Other Options | Parameter | Type | Default | Description | | --- | --- | --- | --- | -| `geofence` | `0` or `1` | Auto | Limits loaded data to a 5 km radius around the center. Automatically enabled when `lat`/`lon` are provided. Set `geofence=0` to load all region data instead. | - -Embedded maps support colour vision palettes via the `?cvd=` URL parameter (e.g., `?cvd=protanopia`). +| `geofence` | `0` or `1` | Auto | Limits loaded data to a 5 km radius. Turns on automatically when `lat`/`lon` are provided. `geofence=0` turns it off. `geofence=1` forces it on around the region centre. | +| `cvd` | string | `none` | Colour vision palette: `none`, `protanopia`, `deuteranopia`, `tritanopia` or `achromatopsia`. | +| `preset` | `freq,bw,sf` | all | Show only one radio preset, e.g. `?preset=910.525,62.5,7`. Leave it out, or use `all`, to show everything. | +| `dir` | any value | off | With `lat`/`lon`, shows a car icon at the centre of the map (e.g. `&dir=1`). | ## Examples @@ -92,6 +93,7 @@ https://yow.meshmapper.net/embed.php?lat=45.4034&lon=-75.7258&geofence=0 - The embed is **read-only** — there are no interactive popups, layer toggles, or controls. - A small "Open on **MeshMapper**" link appears in the bottom-left corner, linking viewers to the full map. - When `lat` and `lon` are provided, the embed automatically geofences data to a 5 km radius for faster loading. Use `geofence=0` to override this. +- The embed needs a browser with WebGL. --- @@ -123,7 +125,8 @@ https://[IATA].meshmapper.net/embed_repeaters.php | Parameter | Type | Default | Description | | --- | --- | --- | --- | -| `mode` | `light` or `dark` | `light` | Sets the initial colour scheme. Users can also toggle between modes using the button in the header. | +| `mode` | `light` or `dark` | `light` | `mode=dark` starts in dark mode; anything else starts in light mode. Users can also switch modes with the button in the header. | +| `preset` | `freq,bw,sf` | all | Show only one radio preset, e.g. `?preset=910.525,62.5,7`. Leave it out, or use `all`, to show everything. | ### Example @@ -133,8 +136,19 @@ https://[IATA].meshmapper.net/embed_repeaters.php https://yow.meshmapper.net/embed_repeaters.php?mode=dark ``` +### What's in the Grid + +The embed shows a **Repeater ID Usage** header, a search box, and filter chips: **All**, **MB**, **Ambiguous**, **2-Byte**, **3-Byte** and **No Location**. + +Cell colours: + +- **Green**: available +- **Blue**: deployed +- **Red**: conflict +- **Dark**: reserved + ### Notes - Clicking a grid cell opens a popup showing whether the ID prefix is available, deployed, in conflict, or reserved, along with the repeater(s) that occupy it. - A "View on **MeshMapper**" link at the bottom opens the full repeater list on the region's map. -- The grid is only available for regions using 1-byte repeater IDs. Multibyte regions will see a "Coming Soon" message instead. +- The grid works in every region. Conflicts take into account whether each repeater supports multi-byte IDs. diff --git a/docs/faq.md b/docs/faq.md index a3b80ac..2a59127 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -11,20 +11,20 @@ MeshMapper is completely free to use. The platform is community-driven and maintained by volunteers. ??? question "How do I get my region added to MeshMapper?" - Use the [new region form](onboarding.md). You need a valid email address and an observer sending data to the MeshMapper or LetsMesh MQTT broker. Linking Discord is optional. + Use the [new region form](onboarding.md). You need a valid email address and at least one observer sending data to the MeshMapper MQTT broker (see [MQTT setup](mqtt-main.md)). Linking Discord is optional. ??? question "What is a region?" A region is a geographic area on MeshMapper that has its own map, administrators, and settings. Regions are typically centered around a city or metropolitan area. Some regions are grouped into multi-region setups that share a single map view. -??? question "My repeater shows as Excluded or Duplicate. Why?" - As a regions mesh network grows, the likelihood of two repeaters sharing the same ID increases. MeshMapper has a robust system for detecting, handling, and resolving these "collisions" to ensure data integrity. Part of this duplicate detection logic is disabling repeaters that share the same ID in order to protect data integrity. [Read more about it here](https://wiki.meshmapper.net/duplicaterepeaterid/). +??? question "My repeater shows as Ambiguous. Why?" + As a region's mesh network grows, two repeaters can end up sharing the same short ID. When MeshMapper can't tell a repeater apart from another at the ID width it advertises, it marks it **Ambiguous** and doesn't credit pings to it. [Read more about it here](duplicaterepeaterid.md). ??? question "Does MeshMapper support multibyte?" - Yes, MeshMapper fully supports multibyte repeater hops/paths. [Read more about it here](https://wiki.meshmapper.net/multibyte/). + Yes, MeshMapper fully supports multibyte repeater hops/paths. [Read more about it here](multibyte.md). ??? question "How long does it take for my region to be onboarded?" - Once the onboarding form is completed, the MeshMapper servers perform an MQTT verification. This checks to ensure that there are observers in the region connected to the MQTT brokers at MeshMapper or letsmesh.net. This process can take up to 5-6 minutes. If verification is successful, the region is presented to the MeshMapper administration team for review. The team will review to ensure boundries are set correctly, read and accomodate any notes added during onboarding, determine if the region should belong to a multiregion, etc. Once complete, the region is deployed. As the process after MQTT verification is manual, the time to complete can vary, but typically regions are onboarded in under 24 hours. + Once the onboarding form is completed, the MeshMapper servers perform an MQTT verification. This checks that an observer in the region is sending data to the MeshMapper MQTT broker (we also accept data seen on the public LetsMesh broker, which isn't MeshMapper infrastructure). This can take up to 5 minutes. If verification is successful, the region is presented to the MeshMapper administration team for review. The team checks that boundaries are set correctly, reads any notes added during onboarding, determine if the region should belong to a multiregion, etc. Once complete, the region is deployed. As the process after MQTT verification is manual, the time to complete can vary, but typically regions are onboarded in under 24 hours. --- @@ -37,22 +37,22 @@ Each colour represents a different type of signal interaction: - **Green (BIDIR)** — Two-way confirmed link - - **Orange (TX)** — Sent a packet, but didn't hear back - - **Purple (RX)** — Heard a response, but didn't transmit - - **Cyan (DISC)** — Discovery packets received - - **Grey (DEAD)** — Repeater heard, but no route available - - **Red (DROP)** — Failed packet delivery + - **Orange (TX)** — Transmitted and routed through the mesh, but no repeats heard back + - **Purple (RX)** — Heard mesh traffic, but didn't transmit + - **Cyan (DISC/TRACE)** — A discovery or trace request got a reply + - **Grey (DEAD)** — A repeater heard it, but no other radio received the repeat + - **Red (DROP)** — No repeats heard and no successful route For more detail, see [Understanding Visuals](visuals.md). ??? question "Do I need the companion app to contribute data?" - 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. + Yes. The MeshMapper companion app is the primary way to submit wardriving data. It is available for both Android and iOS. See [Getting Started](app_getting_started.md) 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, 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. + Yes. Create an account on the [My MeshMapper portal](portal.md), 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 pings. To delete your account itself, contact admin@meshmapper.net. ??? 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. @@ -71,10 +71,10 @@ ## Mobile App ??? question "Where can I download the MeshMapper app?" - The companion app is available on both the Google Play Store (Android) and the Apple App Store (iOS). Search for "MeshMapper" or visit the [App Overview](https://wiki.meshmapper.net/app_overview) page for direct links. + The companion app is available on both the Google Play Store (Android) and the Apple App Store (iOS). Search for "MeshMapper" or visit the [App Overview](app_overview.md) page for direct links. ??? question "How does the app connect to my MeshCore device?" - The app communicates with your MeshCore device over Bluetooth. See the [Connection Guide](app_connection_guide.md) for pairing instructions and troubleshooting tips. + The app connects to your MeshCore device over Bluetooth, over TCP/Wi-Fi, or over USB on Android. See the [Connection Guide](app_connection_guide.md) for pairing instructions and troubleshooting tips. ??? question "How do I join the app beta?" In the MeshMapper Discord server, open **Channels & Roles** and select **Yes** for beta testing. Then use [TestFlight for iOS](https://testflight.apple.com/join/PXxfr5Jr) or the [GitHub APK for Android](https://github.com/MeshMapper/MeshMapper_Project/releases/). Android users can also [add MeshMapper to Obtainium](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22net.meshmapper.app%22%2C%22url%22%3A%22https%3A%2F%2Fgithub.com%2FMeshMapper%2FMeshMapper_Project%22%2C%22author%22%3A%22MeshMapper%22%2C%22name%22%3A%22MeshMapper%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Atrue%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%7D%22%2C%22overrideSource%22%3A%22GitHub%22%7D) to follow prereleases. @@ -119,16 +119,16 @@ Coordinate the new boundaries with neighboring admins, then ask a global administrator. The global panel can merge whole regions, including their sessions, or move pings within a selected area. An area transfer does not move whole sessions. Changing a boundary alone does not move earlier data. ??? question "How big should my region be?" - Draw a boundary around the mesh you expect to map and coordinate it with nearby regions. The onboarding form checks for substantial overlap, and the MeshMapper team reviews each request. See [Defining the Boundary](onboarding.md#defining-the-boundary). + Drop the pin on your area and use **Load Boundary** (State/Prov, County or Local) to pick an OpenStreetMap boundary that matches the mesh you expect to map, and coordinate it with nearby regions. Custom drawn or GeoJSON boundaries are for special cases only. The onboarding form checks for substantial overlap, and the MeshMapper team reviews each request. See [Boundary](onboarding.md#3-boundary). ??? question "Can I use any three letters as my region code?" - No. Pick a recognized IATA airport code near your area. The form checks that the code is available and geographically appropriate; it will suggest nearby codes when one is too far away. See [The Onboarding Form](onboarding.md#the-onboarding-form). + No. Pick a recognized IATA airport code near your area. The form checks that the code is available and geographically appropriate; it will suggest nearby codes when one is too far away. See [Code](onboarding.md#1-code). ??? question "Why does the form say my code is already used or pending?" A code can belong to only one active or pending region. Open that region's subdomain to check its pending status, and contact a Moderator if the request appears stuck. Do not submit another region with a made-up code. ??? question "Why did my onboarding submission fail?" - Read the error shown by the form. It checks the airport code, region name, email, coordinates, radius, boundary polygon and overlap with existing regions. Correct the reported field and retry; if the form says you have submitted too often, wait a few minutes. + Read the error shown by the form. It checks the airport code, region name, email, boundary and overlap with existing regions. Correct the reported field and retry; if the form says you have submitted too often, wait a few minutes. ??? question "Does my area already have a region?" Check the [MeshMapper region map](https://meshmapper.net) before starting a request. If a nearby region can reasonably expand to include your area, contact its administrator first. The new-region form checks for overlap with existing boundaries. @@ -173,10 +173,10 @@ Open your region's admin panel and use **Settings** for the region message, links and public channels. Your own contact details are under **User Settings**. Ask a global administrator to change the region's display name. ??? question "How do I group several companions under one contributor?" - Link your own devices to one [portal account](portal.md#linking-your-companion-devices). Region admins can also group companions in the admin panel's **Users** tab so their contributions appear together on leaderboards. + Link your own devices to one [portal account](portal.md#linking-your-companion-devices). They then appear together as one entry on the leaderboards. ??? question "Can duplicate leaderboard entries or old device data be merged?" - Link the devices you still control to one portal account. If the old device cannot be linked, ask a region administrator to inspect its companion record and the **Users** grouping. Do not delete an account or device record to try to merge history. + Link the devices you still control to one portal account. If the old device cannot be linked, ask a Moderator on Discord for help. Do not delete an account or device record to try to merge history. ### Portal accounts @@ -194,10 +194,10 @@ ## Support & Contributing ??? question "How do I report a bug?" - You can report bugs by tagging the MeshMapper bot on Discord with `!bug` followed by a description, or through the MeshMapper website and mobile app. See [Report Bugs & Features](https://wiki.meshmapper.net/reportbugs) for more info. + You can report bugs by tagging the MeshMapper bot on Discord with `!bug` followed by a description, or through the MeshMapper website and mobile app. See [Report Bugs & Features](reportbugs.md) for more info. ??? question "How do I request a feature?" - Tag the MeshMapper bot on Discord with `!feature` followed by your idea, or through the MeshMapper website or mobile app. See [Report Bugs & Features](https://wiki.meshmapper.net/reportbugs) for more info. + Tag the MeshMapper bot on Discord with `!feature` followed by your idea, or through the MeshMapper website or mobile app. See [Report Bugs & Features](reportbugs.md) for more info. ??? question "Where can I get help if my question isn't answered here?" Try the [MeshMapper Wiki](https://wiki.meshmapper.net) first. If you still need help, post in the MeshMapper Discord server. You can also tag the @MeshMapper AI bot directly and it will do its best to answer based on the wiki and its training. @@ -215,7 +215,7 @@ ??? question "Can I scrape for data or call your API's?" Unauthorized scraping or access to undocumented API's is strictly prohibited and will result in action being taken to protect MeshMapper's data and servers. - The publicly available API's are [listed here](https://wiki.meshmapper.net/coverage-api) and require the use of a provisioned API key. + The publicly available APIs are [listed here](coverage-api.md) and require the use of a provisioned API key. ??? question "Can I have access to the MeshMapper MQTT broker or raw data?" MeshMapper does not offer a public raw MQTT feed. For tools that need map coverage data, use the documented [Coverage API](coverage-api.md) and request an API key. A region admin can configure a broker that sends observer reports *to* MeshMapper; that is separate from read access to MeshMapper's collected data. diff --git a/docs/index.md b/docs/index.md index 8448b09..250abda 100755 --- a/docs/index.md +++ b/docs/index.md @@ -1,7 +1,5 @@ # Welcome to MeshMapper! -# Introduction - **MeshMapper** is a community-driven visualization and analytics platform designed for the **MeshCore** LoRa mesh network. It provides real-time mapping of network coverage and repeater performance, helping communities build more robust and efficient mesh networks. ## What is MeshMapper? @@ -16,18 +14,18 @@ It answers critical questions for mesh operators: ## Administration -Powerful administration options allow regions (or multiregion groups) to manage their own map and its data. [See more about administration here.](https://wiki.meshmapper.net/admins/) +Powerful administration options allow regions (or multiregion groups) to manage their own map and its data. [See more about administration here.](admins.md) ## Core Principles -MeshMapper was desiged to provide realistically reliable data without making assumptions +MeshMapper was designed to provide realistically reliable data without making assumptions. - - **Duplicate Repeaters:** If a repeater with duplicate ID is detected on the mesh (see "Duplicate Repeater IDs" on the left), coverage data is never directly associated with these repeaters. Mapping tools will make suggestions on which repeater was actually involved, but no concrete link will ever be made. - - **Association:** For every data point, repeaters involved in its transmission are associated based on their GPS coordinates. **If a repeater is ever relocated, all links to its coverage data are broken** to ensure actual coverage is not skewed. + - **Duplicate Repeaters:** If a repeater with a [duplicate ID](duplicaterepeaterid.md) is detected on the mesh, coverage data is never directly associated with it. Mapping tools will suggest which repeater was actually involved, but no concrete link will ever be made. + - **Association:** For every data point, repeaters involved in its transmission are associated based on their GPS coordinates. **If a repeater is ever relocated, all links to its coverage data are broken** to ensure actual coverage is not skewed. - **Authentication:** Every wardriving session is validated against known mesh nodes. - - **Privacy:** Wardriving pings do not broadcast your GPS position over the air by default — coordinates travel only to the MeshMapper server. Wardrivers can also view and delete the data they've contributed at any time through the [My MeshMapper portal](https://wiki.meshmapper.net/portal/). + - **Privacy:** Wardriving pings do not broadcast your GPS position over the air by default — coordinates travel only to the MeshMapper server. Wardrivers can also view and delete the data they've contributed at any time through the [My MeshMapper portal](portal.md). -MeshMapper believes in the ownership and control of how a regions data is presented lies with the region itself. If a region chooses to bypass logic designed to limit false or misleading data, that is their choice, and visitors to their map will be warned as such. Repeater owners can easily [opt out of being publicly listed](https://wiki.meshmapper.net/layers/#private-repeaters) on the map. +MeshMapper believes each region should own and control how its data is presented. If a region chooses to bypass the logic that limits false or misleading data, that's their choice, and visitors to their map will be warned. Repeater owners can easily [opt out of being publicly listed](layers.md#private-repeaters) on the map. ## The Wardriving App @@ -35,13 +33,15 @@ Data is collected using the **MeshMapper Wardriver** app, available for both iOS [Download on the App Store](https://apps.apple.com/us/app/meshmapper/id6758073991) | [Get it on Google Play](https://play.google.com/store/apps/details?id=net.meshmapper.app) +See the [Privacy Policy](privacy.md) for what the app collects and how it's used. + ## The Basics - - **The Session**: Before collecting data, the app authenticates with the region and acquires a **Wardriving Session**. Regions have a limited number of active slots (set by that regions administrators) to prevent mesh congestion. + - **The Session**: Before collecting data, the app authenticates with the region and acquires a **Wardriving Session**. Each region has a limited number of transmit slots, set by its administrators, to keep wardriving from overwhelming the mesh. Once those slots are full, new users can still wardrive in passive mode (listening only). - **The Ping**: Once a session is active, the app sends automated messages (pings) through your radio into the mesh at set intervals as you drive, walk, etc. - **The Mesh**: Repeaters in the area receive and re-broadcast your packet. - - **The Ingest**: Specialized "Observer" nodes connected to the map server (via MQTT) listen for these packets and reports them to MeshMapper. - - **The Map**: Data from the app and data from what was heard on the mesh get compared on the backend and display on the map in near-real-time. [See the different levels of coverage MeshMapper can detect.](https://meshmapper.net/img/pingtypes.png) + - **The Ingest**: Specialized "Observer" nodes connected to the map server (via MQTT) listen for these packets and report them to MeshMapper. + - **The Map**: Data from the app is compared with what was heard on the mesh, and the results are displayed on the map in near-real-time. [See the different levels of coverage MeshMapper can detect.](visuals.md#ping-types-defined) [Check out the YOW - Ottawa map](https://yow.meshmapper.net) and adjust the map layers to see just how powerful MeshMapper is! @@ -50,15 +50,12 @@ Data is collected using the **MeshMapper Wardriver** app, available for both iOS ### 1. Network Optimization By visualizing signal paths and dead zones, repeater operators can adjust antenna placement, upgrade hardware, or deploy new repeaters in areas that actually need them. -### 2. Community Building -MeshMapper fosters a sense of shared ownership. Users can see their contributions on the map, compete on **Leaderboards**, earn **Awards**, and manage their own profile and data through the [**My MeshMapper portal**](https://wiki.meshmapper.net/portal/). - -### 3. Hardware Validation +### 2. Hardware Validation The map provides objective data on hardware performance. You can see exactly how far a specific repeater can be heard, or compare the performance of different antennas in real-world conditions. -## Developers +### 3. Community +Every wardriver helps fill in the picture for their local mesh. You can see your own contributions on the map and manage your profile and data through the [My MeshMapper portal](portal.md). [Leaderboards](leaderboards.md) and [awards](awards.md) recognize contributors along the way. -MeshMapper is developed by **MrAlders0n** and **CSP-Tom** of the Greater Ottawa Mesh Radio Enthusiasts. While MeshMapper is 100% free to use, your support helps us cover the backend resources and development time needed to keep up with the rapid global growth. If MeshMapper has helped you, [feel free to buy us a coffee](https://buymeacoffee.com/meshmapper)! +## Developers -## And More! -There's much more to learn and explore. Click the links to the left to navigate to different articles. +MeshMapper is developed by **MrAlders0n** of the Greater Ottawa Mesh Radio Enthusiasts. The backend was started together with **CSP-Tom**, who has since moved on, and MrAlders0n continues that work. While MeshMapper is 100% free to use, your support helps cover the backend resources and development time needed to keep up with the rapid global growth. If MeshMapper has helped you, [feel free to buy us a coffee](https://buymeacoffee.com/meshmapper)! diff --git a/docs/layers.md b/docs/layers.md index db39680..4431b88 100755 --- a/docs/layers.md +++ b/docs/layers.md @@ -1,254 +1,267 @@ # Map Layers & Filters -The MeshMapper map interface offers various layers and filtering options to customize how data is visualized. This allows users to switch between different map styles, toggle specific data types, and drill down into the data based on time, power, or equipment. +This page walks through everything on a region map: the menus, map styles, coverage modes, overlays, tools, settings and filters. -## Base Layers +## The Navigation Bar -You can switch between different underlying map styles using the **Layer Control** (stack icon) in the top-right corner of the map, under **Map Mode**. +| Item | What it does | +| --- | --- | +| **Switch Region** | Jump to another region or multiregion group. Type a city or code to search. | +| **Freq** | Show only pings, repeaters and links on one radio preset (frequency / bandwidth / SF). **All** is the default. Pings from before June 2026 carry no preset and only appear under **All**. | +| **Active Wardrivers** (car icon) | How many wardrivers had an active session when the page loaded. | +| **Filter** | Opens [Filter Map Data](#filters). Shows a count while filters are active. | +| **Region** | Region Info (admins, links, radio presets, settings), Contact Region, Repeater IDs, Repeater List, Observers, Leaderboard and Admin Panel. | +| **Insights** | The packet [Analyzer and Visualize Live](#insights). | +| **Settings** (gear) | Light / Dark Mode toggle, and **Settings** for the options under [Settings](#settings). | - - **Standard**: The default view (OpenFreeMap "Liberty" vector style). Best for general navigation and street names. - - **Bright**: A brighter vector style variant. - - **Dark Mode**: A high-contrast dark theme. Ideal for low-light viewing or when you want the coloured data points to stand out clearly. - - **Topographic**: Displays terrain features, elevation lines, and hill shading. Extremely useful for understanding line-of-sight (LOS) obstructions between repeaters. - - **Satellite** / **Google Satellite** / **Google Hybrid**: Aerial imagery (with street labels in Hybrid). Useful for verifying physical locations, tree cover, and landmarks. +## Base Layers -*Note: Your selected base layer is saved in your browser and will be remembered the next time you visit. Selecting a dark or satellite base automatically switches the interface to dark mode.* +Switch map styles from the **Layer Control** (stack icon, top-right) under **Map Mode**: -## Settings & Preferences + - **Standard**: The default (OpenFreeMap "Liberty"). Best for general navigation and street names. + - **Bright**: A brighter variant. + - **Dark Mode**: A high-contrast dark style that makes coverage stand out. + - **Topographic**: Terrain, elevation lines and hill shading. Useful for spotting line-of-sight obstructions. + - **Satellite** / **Google Satellite** / **Google Hybrid**: Aerial imagery (Hybrid adds street labels). Useful for checking sites, tree cover and landmarks. -The **Settings** menu (gear icon in the navigation bar) provides global options for the interface: +Your choice is remembered in your browser. Turning on Dark Mode from the Settings menu also switches the map to the Dark Mode style. -* **Theme**: Toggle between **Light Mode** and **Dark Mode**. - * *Note: Switching to Dark Mode will automatically change the Base Layer to the "Dark Mode" map style.* -* **Units**: Switch between **Metric** (m/km) and **Imperial** (ft/mi). This setting applies to: - * Distance measurements on connection lines. - * Maximum range calculation. - * Leaderboard statistics. - * Filter panel distance filters. -* **Grid Mode**: Switch between **Simplified** and **Detailed** modes. **Simplified** (default) uses **300m** grid squares, merges cells, and clusters repeaters at wide zoom levels — it loads faster. **Detailed** uses **100m** grid squares with finer coverage detail and non-grouped repeaters. The coverage grid is rendered from cached vector tiles, so the cell size is fixed by the chosen mode at every zoom level. -* **Info Panel**: Switch between **Sidebar** and **Popup** mode for viewing ping details. -* **Hide Data from Missing Repeaters**: When enabled, hides coverage grid squares that reference repeaters no longer present on the map, reducing visual noise from outdated or removed infrastructure. -* **Follow My Location**: When enabled, the map continuously tracks your GPS position and re-centres on it every 5 seconds. Your current zoom level is preserved — only the centre point updates. A blue dot and accuracy circle show your position. Useful for wardriving or moving through a coverage area. Toggle it off to stop tracking; the marker stays at your last known position. -* **Default Zoom**: Set a preferred zoom level that the map loads at. Options range from Street (14) to Region (8). +## Coverage Modes -### My Location +Under **Coverage Mode** in the Layer Control, pick how coverage grid squares are coloured: -The **My Location** button (crosshair icon on the right side of the map) performs a one-time GPS lookup and centres the map on your current position. This works independently of the Follow My Location setting — it's a quick "where am I?" without continuous tracking. +| Mode | Colours grid squares by | +| --- | --- | +| **Standard** | Ping type (BIDIR, TX, RX, and so on). The default. | +| **Effective Coverage** | How reliable coverage is. Each ping type gets a score (BIDIR 3, TX / RX / DISC 2, DEAD 1, DROP 0), averaged per grid square. | +| **Signal Strength** | Signal-to-noise ratio (SNR): ≤ -1 dB is red, ≥ 5 dB is green. | +| **Ping Age** | How recently the square was pinged: green under 30 days, red over 90 days (adjustable in [Settings](#settings)). | +| **Noise Floor** | Background RF noise: green is quiet, red is loud. See [Noise Floor](#noise-floor). | -### Accessibility +### Ping Types -* **Colour Vision**: Choose a colour palette optimised for your vision type. The setting is found under **Settings > Accessibility > Colour Vision**. Available options: - * **Default** — Standard colours (unchanged). - * **Protanopia** (Red-blind) — Optimised for red-green colour vision deficiency. - * **Deuteranopia** (Green-blind) — Same palette as Protanopia (both are red-green CVD). - * **Tritanopia** (Blue-blind) — Optimised for blue-yellow colour vision deficiency. - * **Achromatopsia** (Monochrome) — Greyscale palette for total colour blindness. +In **Standard** mode, the **Coverage** group lets you turn each ping type on or off. It's greyed out in the other modes. - Palettes are based on Wong 2011 colourblind-safe colours. When a palette is selected, all coverage grid squares, repeater markers, signal strength indicators, legend colours, summary stats, charts, and gradient layers (Effective Coverage, Signal Strength, Ping Age) update automatically. The setting is saved in your browser and persists across sessions. +| Type | Colour | Meaning | +| --- | --- | --- | +| **BIDIR** | Green | Heard repeats from the mesh **and** successfully routed through it. | +| **TX** | Orange | Successfully routed through, but no repeats heard back. | +| **RX** | Purple | Heard mesh traffic but did not transmit. | +| **DISC/TRACE** | Cyan | A discovery or trace reply was heard. | +| **DEAD** | Grey | A repeater heard it, but no other radio received the repeat. | +| **DROP** | Red | No repeats heard **and** no successful route. | -### Effective Coverage +See [Ping Types Defined](visuals.md#ping-types-defined) for more detail. + +### Noise Floor -* **Colour Spectrum**: Toggle between **Red → Green** (default) and **Red → Blue** (full spectrum) for the Effective Coverage layer. -* **Min Sample Size**: Set the minimum number of pings required in a grid square before it is displayed on the map (default: 1). Increasing this value filters out grid squares with limited data, giving a cleaner view of well-sampled areas. +Every companion reports a **noise floor** reading (in dBm) with each ping: the level of background RF interference at that spot. Closer to 0 dBm is loud; very negative (e.g. -120 dBm) is quiet. -### Grid Transparency +Different radios report different absolute values, so MeshMapper shows a **noise delta** instead: how much louder a spot is than that companion's usual baseline. -* **Normal Opacity**: Adjust the fill opacity of coverage grid squares (default: 60%). -* **Faded Opacity**: Adjust the opacity of grid squares that are faded into the background, such as when the Repeater Neighbours layer is active (default: 15%). + 1. Once a companion has at least 5 readings, its **baseline** is its 10th-percentile reading (roughly the quietest conditions it sees). + 2. Each reading is scored as the difference from that baseline. + 3. Baselines are recalculated regularly. -### Line Transparency +For example, with a baseline of **-110 dBm**, a reading of **-90 dBm** is **+20 dB**: 100× noisier than usual. Readings in the same grid square are averaged. -* **Line Opacity**: Adjust the opacity of all lines drawn on the map — including repeater neighbour lines, repeater-to-grid-square lines, and ping-to-repeater lines (default: 100%). +A **Noise Floor** legend (Quiet → Loud) appears in the bottom-right while this mode is on. -## Overlay Layers +## Overlays -These layers display the actual mesh network data. You can toggle them on or off individually to reduce clutter. +Toggle these in the Layer Control. Some may be greyed out as **Disabled by Administrator** in regions that hide them. -| Layer Name | Description | +| Overlay | What it shows | | --- | --- | -| **BIDIR** | **Green** grid squares showing confirmed two-way coverage (the sender heard a repeat AND the packet was also heard by at least one observer after being repeated). | -| **TX** | **Orange** grid squares where packets were sent but no confirmation was received (no repeat heard by the sender but the packet was repeated and heard by at least one observer). | -| **RX** | **Purple** grid squares where other repeated mesh traffic was heard by the meshmapper companion. | -| **DISC / TRACE** | **Cyan** grid squares showing Node Discovery and Trace packets. | -| **DEAD** | **Grey** grid squares where a repeater heard the ping, but it didn't route further (sender heard a repeat but no observer did). | -| **DROP** | **Red** grid squares showing failed pings (neither the sender nor any observers heard repeats of the packet). | -| **Repeaters** | The chips representing repeater nodes. Each one carries its hex ID, with its state on the chip's left edge and border. See [Repeaters](visuals.md#repeaters). | -| **Repeater Coverage** | When a repeater is clicked, this layer draws dashed blue lines to all locations where that repeater was heard. Useful for visualizing the effective footprint of a specific repeater. | -| **Adv. Repeater Coverage** | Similar to standard Repeater Coverage, but colour-codes the lines and grid squares based on the connection type (Green=BIDIR, Orange=TX, etc.) instead of using a uniform blue. Lines are labelled as **In** or **Out** to indicate whether the ping originated inside or outside the region boundary. | -| **Repeater Neighbours** | Draws lines between repeaters that are known to reach each other, with full support for multi-byte repeater identification. When enabled, coverage pings fade into the background to make the neighbour lines easier to trace. All four kinds are drawn solid, so the colour is what tells them apart. Inferred lines are hidden once the region's retention window closes, which is 7 days unless the region administrator changed it.
- **Green**: Inferred, seen in a packet path an observer heard within the last 3 days.
- **Orange**: Inferred, older than 3 days.
- **Blue**: Reported by the repeater over the air.
- **Purple**: Uploaded from the app by an admin.
See [Links Between Repeaters](visuals.md#links-between-repeaters). | -| **Backbone** | The smallest set of repeaters whose links together carry half the region's traffic, with **gold** chips for the sites and coloured lines (trunks) between them. Each chip's label shows that repeater's own share. Switching this on hides every repeater that is not a backbone site, turns **Repeaters** on, and turns **Repeater Neighbours** off. See [The Backbone](visuals.md#the-backbone). | -| **Effective Coverage** | Filters the map to show only locations with confirmed reliable connectivity, removing noise and edge-case pings for a cleaner view of where the mesh truly delivers. Each ping type is given a numerical value (BIDIR being the highest and DROP being the lowest) and these values are averaged across each grid square.| -| **Signal Strength** | Colour-codes coverage grid squares by signal strength (SNR), making it easy to identify strong and weak zones across the map at a glance. ≤ -1 dB displays in red and ≥ 5 dB in green, with everything else in between. | -| **Ping Age** | Colour-codes grid squares based on how recently they were last pinged. Green indicates recent activity and red indicates stale coverage. The green and red age thresholds are adjustable from the Settings panel, making it easy to identify areas that may need remapping. | -| **Noise Floor** | A coverage mode that colour-codes grid squares by RF noise level. **Green** = quiet, **Red** = loud. Select it from the **Coverage Mode** section. See [Noise Floor](#noise-floor) below for details. | -| **Neighbor Zones** | Small pins showing the location of nearby MeshMapper regions. Clicking them will take you to that map. | -| **Neighbour Zone Boundaries** | Draws a dashed outline showing the official boundary (polygon or radius) of each neighbouring region. Requires **Neighbor Zones** to be enabled — it will be automatically turned off when Neighbor Zones is disabled, and restored when it is re-enabled. | -| **Region Boundary** | A black outline showing the official area covered by the current map zone. | +| **Repeaters** | Repeater chips, each with its hex ID and state. See [Repeaters](visuals.md#repeaters). | +| **Repeater Coverage** | Click a repeater to see where it was heard: grid squares and dashed lines coloured by ping type (DROP is left out). With this overlay off, the squares show in plain blue with no lines. | +| **Repeater Neighbours** | Lines between repeaters that reach each other. **Green**: seen in a packet path in the last 3 days. **Orange**: seen longer ago. **Blue**: reported by the repeater. **Purple**: uploaded from the app. Coverage fades while this is on. See [Links Between Repeaters](visuals.md#links-between-repeaters). | +| **Repeater Scopes** | Which repeaters carry a mesh scope, and the links between them. See [Repeater Scopes](#repeater-scopes). | +| **Backbone** | The repeaters and links that carry half of the region's traffic, in **gold**. Only backbone repeaters are shown while it's on. See [Backbone](backbone.md) for how it's calculated. | +| **Neighbour Zones** | Pins for nearby MeshMapper regions. Click one to open that map. | +| **Neighbour Zone Boundaries** | Dashed outlines of nearby regions. Needs **Neighbour Zones** on. | +| **Region Boundary** | This region's boundary (black, or white on dark and satellite maps). | -### Noise Floor +Only one of **Repeater Neighbours**, **Repeater Scopes** and **Backbone** can be on at a time. Turning one on turns the others off. -The **Noise Floor** coverage mode visualizes the RF noise environment across the map by colour-coding grid squares. It helps identify areas with high interference versus quiet areas with clean signal conditions. +### Repeater Scopes -#### What It Shows +MeshCore repeaters can be set up with named **scopes** (e.g. `yow`). A message tagged with a scope is only forwarded by repeaters that carry that scope. **✱ Not set** means the repeater only passes messages with no scope. -Every companion reports a **noise floor** reading (in dBm) with each ping it submits. The noise floor represents the level of background RF interference the radio is experiencing at that location. A reading closer to 0 dBm is "loud" (lots of interference), while a very negative value like -120 dBm is "quiet." +Turn on **Repeater Scopes** and pick a scope from the bar at the bottom of the map. The map shows only the repeaters that carry it, and draws a link between two of them when both carry it. The bar shows how many repeaters and links match. -Because different radios and antennas report different absolute noise values, MeshMapper doesn't display the raw readings directly. Instead, it calculates a **noise delta** — how much louder or quieter a location is compared to that device's baseline. +MeshMapper learns a repeater's scopes three ways: -#### How Calibration Works + - **I** (Inferred): seen forwarding traffic in that scope. + - **R** (Reported): the repeater listed it when an observer asked. + - **U** (Uploaded): a wardriver's app asked the repeater and uploaded its answer. -MeshMapper automatically calibrates each companion's baseline: +A **★** marks the repeater's default scope (the one on its own adverts). Repeaters with firmware older than v1.12 can't answer scope queries. -1. After enough data has been collected (at least 5 readings), MeshMapper calculates the companion's **10th percentile** noise floor — essentially the quietest conditions that companion typically experiences. -2. This becomes the companion's **baseline**. -3. Every data point is then scored as a **delta** (difference) from that baseline. -4. Every day a new calibration is done to update that companion's noise delta. +To check whether a scope name is in use in your region, use the [Scope Finder](#scope-finder). -For example, if your companion's baseline is **-110 dBm** and you submit a reading of **-90 dBm**, the delta is **+20** — meaning that location is 20 dB (100X) noisier than your device sees under typical quiet conditions. +## Map Tools -This per-companion calibration ensures that readings from different hardware/setups are comparable on the same map. All readings for a single location are averaged and displayed accordingly. +Open **Map Tools** (the tools icon on the map). One tool is open at a time. -#### Reading the Colours +### Line of Sight -Grid squares are colour-coded on a gradient from green to red: +Check terrain clearance between two or more points. -| Colour | Meaning | -| --- | --- | -| **Green** | Quiet — at or near the companion's baseline noise level. | -| **Yellow** | Moderate — some elevated noise above baseline. | -| **Red** | Loud — significantly above baseline, indicating high interference. | + 1. Click the map or a repeater to place points **A** and **B** (or type coordinates). Use **Add Point** for more. + 2. Set each point's **Height** above ground. Points placed on a repeater start at 3 m. + 3. Check the **Freq** (defaults to your region's most-used frequency). + 4. Click **Calculate**. -A **Noise Floor** legend appears in the bottom-right of the map when this mode is active, showing the gradient scale from Quiet to Loud. +The result shows the elevation profile (with earth curvature) and the first Fresnel zone, and rates each leg: **Line of Sight CLEAR**, **Minor Fresnel Intrusion**, **Fresnel Zone Partially Blocked** (less than 60% clear) or **Line of Sight OBSTRUCTED**. On the map, green is clear and red is blocked. -Like the other coverage modes, Noise Floor fully supports the [colour vision accessibility options](#accessibility), so all colour blindness palettes apply to noise grid squares and the legend. +### Antenna Coverage -!!! tip - To enable, select **Noise Floor** from the **Coverage Mode** section in the Layer Control (stack icon) in the top-right corner of the map. +Estimate how far a radio at a spot could reach, using terrain. -### Legacy Data Layer + 1. Tap the map (or a repeater) to place the pin. + 2. Pick the transmit **power** (14–30 dBm, default 22) and set the **TX** and **RX heights** (defaults 6 m and 2 m). The frequency is set from your region's most-used band. + 3. Optionally open **Advanced** for sensitivity, spreading factor, antenna gains, cable loss, fade margin and environment. The defaults suit most setups. -Regions with imported historical data will have a **Legacy** layer available. This layer displays data points uploaded via CSV but does not show connection lines or contribute to repeater statistics due to the lack of verifiable repeater association. See [Data Upload](https://wiki.meshmapper.net/dataupload/) for more details. +The map shades **Strong** (red), **Likely** (orange) and **Fringe** (yellow) areas, and shows how far each reaches plus the approximate area covered. -## Map Tools +!!! note + This is an estimate from bare-ground terrain. Buildings, trees, antennas and weather all change real-world range. Treat it as a guide, not a guarantee. -### Line of Sight +### Coverage Timeline -The **Line of Sight** tool is available from the map toolbar and allows you to check terrain clearance between any number of points on the map. Click to place two (or more) points (or click directly on repeaters) and MeshMapper will fetch the elevation profile and show whether the path is clear or obstructed. When a repeater is selected as one of the endpoints, you can adjust its elevation above ground for more accurate results. +An animated playback of how the region's coverage grew, from its earliest data to today. A playback bar at the bottom lets you **Play/Pause**, **drag** to jump to a date, and click the speed to cycle **1x → 2x → 4x → 0.5x**. -### Coverage Timeline +### Scope Finder -The **Coverage Timeline** tool provides an animated playback of how a region's coverage has grown over time, from the region's earliest data to the present day. It is available from the **Map Tools** (wrench icon) control. +Test whether a scope name is used in your region. Type the name (e.g. `yow`) and click **Find**. MeshMapper checks it against the region's recent scoped traffic and tells you whether it's already tracked, found, only weakly matched, or not found. If a scope is found but not yet monitored, a region admin can add it under **Repeaters, Neighbours & Scopes** in the admin panel. -When activated, a playback bar appears at the bottom of the screen with controls to: +### 3D Terrain -- **Play/Pause** — automatically advance the timeline -- **Scrub** — drag the slider to jump to a specific point in time -- **Speed** — click the speed label to cycle through playback speeds (0.5x, 1x, 2x, 4x) +The **3D Terrain** control (landscape icon, top of the map controls) drapes the map and coverage over real terrain. -The playback runs on the live vector coverage data, so you can watch coverage fill in as wardrivers contributed data over weeks and months. + - **Enable 3D**: turn terrain on or off. + - **Hillshade relief**: add shaded relief. + - **Exaggeration**: 0.5× to 2.5× (default 1.4×). + - Right-drag (or Ctrl-drag) to tilt and rotate. -### 3D Terrain +### My Location -The **3D Terrain** control (landscape icon at the top of the map controls) drapes the map — including all coverage data — over real elevation terrain: +The **Show My Location** button (top-right) finds your position once and zooms to it. For continuous tracking, turn on **Follow My Location** in [Settings](#settings). -- **Enable 3D** — Toggles the terrain on or off -- **Hillshade relief** — Adds shaded relief for depth -- **Exaggeration** — A slider (0.5×–2.5×) to emphasize elevation differences -- **Tilt/rotate** the view by right-dragging (or ctrl-dragging) the map +## Insights -3D terrain makes it much easier to see how hills and valleys shape your region's RF coverage. +The **Insights** menu has two packet tools: -### Packet Analyzer + - **Analyzer**: opens the MeshMapper packet analyzer for this region in a new tab, showing raw packets heard by the region's observers. + - **Visualize Live**: animates packets on the map in real time. Each packet is an orange dot that travels its actual path through the repeaters to the observer that heard it, and repeaters flash as it passes. Click **Exit Live Visualization** to stop. -The **Packet Analyzer** provides a real-time view of raw MeshCore packets flowing through the region's MQTT observers. It is accessible from the map toolbar. The analyzer can be opened in a new tab for a full-screen experience using the pop-out button. +## Settings -The **Live Visualization** mode (accessed via the "Visualize Live" button in the analyzer) draws animated lines on the map showing how packets are moving through the region's repeaters in real time. +Open **Settings** from the gear menu. Settings are saved in your browser. -## Linking to a Specific Location +### Map Display -You can open a region's map pre-centred on an exact spot by adding `lat`, `lon`, and (optionally) `zoom` query parameters to its URL. This is useful for sharing a precise location — a specific repeater site, a coverage gap, or a spot you want someone else to look at — without them having to pan and zoom to find it. + - **Units**: **Metric** (m/km) or **Imperial** (ft/mi). Applies to distances on the map, filters and leaderboards. + - **Grid Mode**: **Simplified** (default) uses 300 m grid squares, merges cells and groups repeaters at wide zoom, and loads faster. **Detailed** uses 100 m grid squares and shows every repeater. Changing it reloads the page. + - **Default Zoom**: the zoom the map opens at, from **14 - Street** to **8 - Region**. + - **Info Panel**: show details in a **Sidebar** or a **Popup**. -``` -https://[IATA].meshmapper.net/?lat=45.4034&lon=-75.7258&zoom=15 -``` +### Map Behaviour -| Parameter | Type | Default | Description | -| --- | --- | --- | --- | -| `lat` | float | Region centre | Latitude to centre the map on (−90 to 90). | -| `lon` | float | Region centre | Longitude to centre the map on (−180 to 180). | -| `zoom` | integer | `13` | Map zoom level. Clamped to the 3–19 range. | + - **Hide Missing-Repeater Data**: hide pings from repeaters no longer on the network. + - **Follow My Location**: keep the map centred on your GPS position (updated every 5 seconds, keeping your zoom). A blue dot and accuracy circle show where you are. -**Example — open the YOW map centred on Parliament Hill at zoom 16:** +### Accessibility -``` -https://yow.meshmapper.net/?lat=45.4236&lon=-75.7009&zoom=16 -``` +**Colour Vision** changes the colours used across the map (grid squares, repeaters, lines, legends, charts and coverage modes): -!!! note - - Both `lat` and `lon` must be present and valid for the deep link to take effect. If either is missing or out of range, the map ignores it and loads normally at the region's default view. - - The deep-link position is preserved even after the coverage data finishes loading — the map will not snap back to the region's default extent. - - A `lat`/`lon` deep link takes precedence over the `location` place-name search (below). + - **Default** + - **Protanopia (Red-blind)** + - **Deuteranopia (Green-blind)**: same palette as Protanopia. + - **Tritanopia (Blue-blind)** + - **Achromatopsia (Monochrome)** -!!! tip - To share a read-only, embeddable version of the map at a fixed location instead, see [Map Embedding](embedding.md) — it accepts the same `lat`/`lon`/`zoom` parameters on the `embed.php` view. +### Effective Coverage -### Searching by Place Name + - **Colour Spectrum**: **Red → Green** (default) or **Red → Blue**. + - **Min Sample Size**: hide grid squares with fewer pings than this (1–20, default 1). -If you don't have exact coordinates, append `location=` with a place name or address instead. The map geocodes it and centres there on load: +### Ping Age -``` -https://yow.meshmapper.net/?location=Parliament%20Hill,%20Ottawa -``` + - **Green (under)**: squares pinged more recently than this are green (default 30 days). + - **Red (over)**: squares older than this are red (default 90 days). + +### Transparency + + - **Normal Opacity**: coverage grid squares (default 60%). + - **Faded Opacity**: grid squares faded into the background, e.g. behind Repeater Neighbours (default 15%). + - **Line Opacity**: all lines on the map (default 100%). + +## Filters + +Click **Filter** in the navigation bar to open **Filter Map Data**. Filters apply everywhere: grid squares, popups, charts and ping history. Active filters show as removable chips, and applying them keeps your current map view. -If both are supplied, an explicit `lat`/`lon` deep link always wins over `location`. + - **Time** + - **Show data from**: All time, Last 30 days, Last 90 days or Last year. + - **From date / To date**: a custom date range. + - **Signal** + - **Transmit power**: Any power, 0.3 W, 0.6 W or 1.0 W. + - **Min / Max signal**: signal-to-noise ratio (dB). + - **Location** + - **Min / Max distance**: distance between the ping and the repeater (in your units). + - **Repeaters** + - **Repeater name or ID**: show only matching repeaters. + - **ID width**: pings whose path uses 1-, 2- or 3-byte repeater IDs. This is not the number of hops. + - **Ping mentions repeater**: pings that went through or were heard from a repeater. Pings where that repeater's ID is ambiguous are left out. + - **Repeater Scope**: repeaters carrying a scope (only shown when the region has scopes). + - **Only external antennas**: pings collected with an external antenna. + - **Only repeaters with the wrong time**: repeaters whose clock is off by more than 120 seconds. -## Search & Filters +To filter by radio preset, use **Freq** in the navigation bar. -The search functionality combines quick lookups with powerful filtering options. +## Sharing a Map View -### Filter Map Data -Clicking the **Filter** pill (tune icon) in the navigation bar opens the **Filter Map Data** panel. Filters are applied server-side — the coverage grid, click popups, charts, and ping history all reflect the same filtered dataset. Active filters appear as removable chips, and the Filter pill shows a count and lights up cyan while filters are active. +The address bar updates as you move around and change layers, so copying the URL shares exactly what you see. Repeater and ping popups also have a **Copy Link** button. -To see several neighboring regions together, open their [multiregion group map](multiregions.md) if one exists. The global homepage is a region index; use a region or group map for its coverage tiles. +You can also build links by hand: - - **Time**: - - **Show data from**: All time, Last 30 days, Last 90 days, or Last year. - - **From date / To date**: Specify a custom date range. - - **Signal**: - - **Transmit power**: Any power, 0.3 W, 0.6 W, or 1.0 W. - - **Radio config**: Filter by the radio preset (frequency / bandwidth / SF / CR) the wardriver's device reported — useful in regions where multiple radio configurations are in use. - - **Min / Max signal**: Filter pings by Signal-to-Noise Ratio (dB). - - **Location**: - - **Min / Max distance**: Filter pings by distance from the heard repeater (in your selected units). - - **Repeaters**: - - **Repeater name or ID**: Show only specific repeaters by name or hex ID. - - **Hops away**: Filter by hop count (1, 2, or 3 hops). - - **Ping mentions repeater**: Find pings that routed through or were heard from a specific repeater by its name or ID. This filter automatically excludes pings associated with duplicate repeater IDs or known collisions and displays a warning message when this occurs. - - **Only external antennas**: Show only data points collected with an external antenna. - - **Only repeaters with the wrong time**: Show only repeaters whose embedded clock is off by more than 120 seconds. Useful for identifying repeaters that need their time set correctly. - - **User**: - - **User name**: Filter pings by the (full or partial) username of the wardriver (if enabled for the region). +``` +https://yow.meshmapper.net/?lat=45.4236&lon=-75.7009&zoom=16&m=sat&l=rep.nbr.rb +``` -!!! tip "Filters preserve your map position" - Applying, resetting, or changing filters no longer resets the map to its default centre and zoom. Your current view is preserved so you can refine filters while staying focused on a specific area. +| Parameter | What it does | +| --- | --- | +| `lat`, `lon` | Centre the map here. Both are needed. | +| `zoom` | Zoom level, 3–19 (default 13). Decimals work. | +| `location` | A place name or address to look up and centre on (zoom 15), e.g. `location=Parliament%20Hill,%20Ottawa`. `lat`/`lon` win if both are given. | +| `m` | Base map: `std`, `brt`, `dark`, `topo`, `sat`, `gsat` or `ghyb`. | +| `l` | Overlays to turn on, separated by dots: `rep` Repeaters, `rcov` Repeater Coverage, `nbr` Repeater Neighbours, `sc` Repeater Scopes, `bb` Backbone, `nz` Neighbour Zones, `nzb` Neighbour Zone Boundaries, `rb` Region Boundary. Anything left out is off. | +| `cm` | Coverage mode: `std`, `eff`, `sig`, `age` or `noise`. | +| `preset` | Radio preset: `all`, or `freq,bw,sf` (e.g. `910.525,62.5,7`). | +| `repeater` | Open a repeater by its ID or full public key. | +| `ping` | Open the grid square at `lat,lon`. | +| `repeater_list`, `repeater_ids`, `observers` | Open that list on load. | +| `live` | Start Visualize Live on load. | +| `coverage-only` | Open in [Coverage Only Mode](#coverage-only-mode). | + +Settings from a link only apply to that visit; they don't change your saved preferences. + +!!! tip + To embed a read-only map in another site, see [Map Embedding](embedding.md). ## Coverage Only Mode -For users on older hardware, mobile devices with limited resources, or slow internet connections, MeshMapper offers a **Coverage Only Mode**. +For older devices or slow connections, **Coverage Only Mode** loads just the coverage grid as lightweight tiles. - - **How it works**: Instead of the full interactive interface, this mode loads just the coverage grid as lightweight map tiles from the server, skipping repeaters, popups, and all the interactive machinery. - - **Performance**: This significantly reduces memory usage and load times, making the map usable on almost any device regardless of processing power. - - **Limitations**: - - **No interactivity**: You cannot click on grid squares to see pings or repeater paths. - - **No filtering**: Advanced filters (Time, Power, User) are disabled. - - **Simplified View**: Only the coverage grid is shown; repeaters and lines are hidden. - - **How to access**: - - A "Switch to Coverage Only" button will appear on the loading screen. + - **How to open it**: click **Switch to Coverage Only** on the loading screen, or add `?coverage-only` to the map's URL. + - **What you lose**: no overlays, no clicking on grid squares, no filters, and no Map Tools or 3D. Base maps and My Location still work. + - **To leave**: click **Exit Coverage Only**. ## Private Repeaters -Operators can opt-out of location sharing by appending the "no entry" emoji (🚫) to the end of their repeater's name. +Repeater owners can hide a repeater's location by adding the "no entry" emoji (🚫) to the start or end of its name. - - **Map**: The Name, Location, and ID are removed from the map and the **Repeaters** layer. - - **Pings**: Coverage pings are kept and visible in the grid layers, but the repeater details are masked. - - **Leaderboards**: The name is replaced with "(private repeater)", but stats are still calculated. + - **Map**: the repeater isn't drawn. It's listed as **Hidden** in the Repeater IDs list, so its ID isn't reused by mistake. + - **Pings**: coverage is kept, but the repeater shows as **(hidden)** with no lines or distances. + - **Leaderboards**: the name shows as "(private repeater)", but its stats still count. diff --git a/docs/leaderboards.md b/docs/leaderboards.md index ce34318..cde0e3a 100755 --- a/docs/leaderboards.md +++ b/docs/leaderboards.md @@ -1,75 +1,70 @@ # Leaderboards & Statistics -The Leaderboard page provides a real-time statistical overview of a regions performance, user contributions, and repeater capabilities. +Each region has a Leaderboard page (**Region → Leaderboard**) with statistics about the region, its wardrivers and its repeaters. There's also a [Global Leaderboard](#global-leaderboard) across every region. + +Leaderboards are refreshed **once a day**, so recent pings can take up to 24 hours to show up. The page shows when it was last updated. ## Region Statistics -At the top of the page, you will find high-level metrics for the current region. Leaderboard data is cached and regenerated about **once a day**, so recent contributions can take up to 24 hours to appear. +The **Stats** card at the top of the page: + + - **Total Data Points**: every ping collected in the region (all types). + - **Ping breakdown**: **Bidirectional** (green), **TX Only** (orange), **RX Only** (purple), **Discovery** (cyan, including TRACE), **Dead** (grey) and **Dropped** (red). See [Ping Types](visuals.md#ping-types-defined). + - **Active Repeaters**: repeaters on the map, including Ambiguous ones. Disabled and Inactive repeaters aren't counted. + - **Estimated Coverage**: the share of mapped grid squares with working coverage (BIDIR, TX, RX, DISC or TRACE). Squares with only DEAD or DROP pings count as not covered. + - **Contributors**: how many different wardrivers have contributed. + - **Total Grid Squares**: how many 300 m squares have at least one ping. This always uses the 300 m grid, whatever your Grid Mode setting. - - **Total Data Points**: The aggregate number of valid pings collected in the database. - - **Ping Breakdown**: - - **Bidirectional (Green)**: Confirmed two-way links. - - **TX Only (Orange)**: Packets sent by the user and heard by the mesh, but no confirmation was received back. - - **RX Only (Purple)**: Packets heard by the user (e.g., telemetry), but the user did not transmit. - - **Discovery (Cyan)**: Node discovery packets. - - **Dead/Dropped**: Failed packets or those that hit a repeater but did not route further. - - **Active Repeaters**: The count of repeaters currently online and trusted. **Note:** Repeaters flagged as "Duplicate" or "Excluded" are not counted here. - - **Estimated Coverage**: A percentage representing how much of the mapped grid contains valid coverage (BIDIR, TX, DISC, RX). - - **Contributors**: The number of unique users who have contributed data to the region. - - **Total Grid Squares**: The total number of unique ~300m grid squares that have been mapped by at least one user. This metric always uses the 300m grid regardless of the user's Grid Mode setting. +## Wardriver Leaderboards -## User Leaderboards +Each board shows the top 10. -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)). +**Points**: 1 point per ping, plus **1.5 points** for each square where the app's Smart Pinging saved a ping (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. + - **Top Contributors (7 Days)**: points from the last 7 days. + - **All Time Legends**: every point ever earned in the region. + - **Top Explorers**: how many different 300 m squares you've pinged in. Being first doesn't matter. + - **Top Pioneers**: squares you pinged **before anyone else**. One person per square, forever. + - **Top Airtime Savers**: see below. + - **Most Repeaters Administered**: active repeaters this person has logged in to as admin from the app. -### Top Explorers -This leaderboard rewards **exploration** — covering new ground rather than re-driving the same routes. It counts the number of unique ~300m grid squares where each user placed the **first-ever ping**. This metric always uses the 300m grid regardless of the user's Grid Mode setting. If a grid square has been pinged 100 times by 10 different users, only the user who mapped it first gets credit. All coverage types count (BIDIR, TX, RX, DISC, DEAD, DROP). +The top three places show their rank in **gold**, **silver** and **bronze**. -| Ranking | Indicator | -| --- | --- | -| **1st** | **Gold** Number | -| **2nd** | **Silver** Number | -| **3rd** | **Bronze** Number | +Wardrivers are listed by device, or by their **My MeshMapper** account if they've linked one (all of an account's devices are combined into one row, with a 🔗 badge). Wardrivers without a name show as **Anonymous** and aren't ranked. Click **Profiles** to look up a wardriver's stats and [awards](awards.md). ### 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 +When the app's [Smart Pinging](app_wardriving_modes.md#smart-pinging) skips a ping because a square already has recent good coverage, that square earns **1.5 points** once it's verified against the region's coverage. Each square counts once per session. This board ranks wardrivers by those points alone; they're also included in the totals above. -These tables highlight the performance of the infrastructure itself. +## Repeater Leaderboards ### Best Repeaters (Ping Count) -This ranks repeaters by how much traffic they have handled. The table shows both the **total ping count** and the number of **unique grid squares** the repeater has been heard from — click either column header to sort by that metric. -### Best Repeaters (Max Range) -This ranks repeaters by the furthest distance (in km/m) they have achieved a link. The table is broken down by signal type to show different propagation characteristics: +Repeaters heard directly the most times. Sort by **Pings** (total) or **Grids** (different squares heard from). RX-only pings aren't counted. - - **BIDIR (Green)**: Max distance where a solid **two-way** link was established. - - **TX (Orange)**: Max distance where the repeater heard the user (but the user didn't hear the confirmation). This often indicates the repeater has a better "ear" (receive sensitivity) than the user. - - **RX (Purple)**: Max distance where the user heard the repeater (but didn't transmit). This indicates the repeater has a strong transmit signal. - -*Tip: You can click the headers (BIDIR, TX, RX) to sort the table by that specific metric.* +### Best Repeaters (Max Range) -## Global Leaderboard +The single longest confirmed contact for each repeater, by ping type: **BIDIR**, **TX**, **RX**, **DISC** and **DEAD**. Click a column to sort by it. Distances over 500 km are ignored. -The [Global Leaderboard](https://meshmapper.net/global_leaderboard.php) aggregates data from all active regions into a single view. It is regenerated daily by a scheduled task and includes: +### Notes - - **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. + - **Ambiguous repeaters** stay listed, marked with a red **\*** ("Ambiguous ID"). Pings where their ID was ambiguous don't count towards them. See [Duplicate Repeater IDs](duplicaterepeaterid.md). + - **Private repeaters** (🚫 in the name) show as "(private repeater)". + - Regions that hide repeater detail don't show the repeater boards. + - Regions that [turn off duplicate detection](overrideduplicates.md) show a warning that repeater statistics may be inaccurate. -Each user's **primary region** is determined by where they have contributed the most data points. Contributors are de-duplicated by device public key, so the same node heard in several regions counts as one entry. +## Global Leaderboard -## Contests +The [Global Leaderboard](https://meshmapper.net/global_leaderboard.php) combines every region and is also refreshed daily. -During special events (e.g., **Holiday Wardrive Contest**), a special leaderboard card will appear at the top of the page. + - **Global Stats**: + - **Network**: Active Regions, Countries, Repeaters, Multibyte (%), Observers and Companions. + - **Packets**: the same ping breakdown as a region. + - **Activity**: Data Points, Grid Squares, Wardrivers, Live Now, Users (24h) and Sessions (24h). + - **Wardriver boards**: **Top Wardrivers (7 Days)**, **All Time Legends**, **Top Explorers**, **Top Pioneers**, **Top Airtime Savers** and **Most Repeaters Administered**, each showing the wardriver's **primary region** (where they've earned the most points). + - **Region boards**: **Most Repeaters**, **Most Grid Squares**, **Most Data Points** and **Most Wardrivers**. + - **Repeater boards**: **Best Repeaters (Ping Count)** and **Best Repeaters (Max Range)** from every region, linking back to each repeater on its region's map. + - **Multibyte Upgrade Board**: regions ranked by how many of their repeaters are [multi-byte](multibyte.md) capable. + - **Scope Onboarding**: how many of each region's repeaters carry a mesh scope, with a 90-day trend. - - **Time-Limited**: Only pings collected within the specific contest start and end dates are counted. - - **Exclusions**: Developers, administrators, and contest organizers are often excluded from these rankings to ensure fairness. - - **Live Updates**: Like the other boards, this updates in near real-time as data is submitted. \ No newline at end of file +Regions that hide repeater detail or [turn off duplicate detection](overrideduplicates.md) don't send their repeaters to the global board. Their wardrivers and coverage still count. diff --git a/docs/mqtt-firmware.md b/docs/mqtt-firmware.md new file mode 100644 index 0000000..16e0a1f --- /dev/null +++ b/docs/mqtt-firmware.md @@ -0,0 +1,49 @@ +# MeshCore MQTT Native Firmware + +These instructions cover setting up the MeshCore observer firmware to send to MeshMapper. The firmware runs directly on an ESP-based radio with Wi-Fi, so no extra computer is needed. It has a built-in **MeshMapper** broker preset. + +*The observer firmware is built by HerculesMulligan. For advanced options, see the [MeshCore Observer Setup Guide](https://observer.gessaman.com/docs).* + +## Prerequisites + + - An ESP-based MeshCore device with Wi-Fi (e.g. Heltec V3/V4, Station G2) + - A Wi-Fi network the observer can stay connected to + - Chrome or Edge (for flashing from the browser) + +## 1. Flash the Firmware + +Open the [MeshCore Observer Flasher](https://observer.gessaman.com/), pick **MQTT Observer Firmware**, select your device, and flash it from the browser. + +## 2. Configure the Observer + +### Option 1. Setup Wizard + +On first boot, the observer creates a Wi-Fi network named **MeshCore-Setup-XXXX**. + +1. Connect to it from your phone or computer. The setup page opens automatically (or browse to `http://192.168.4.1/`). +2. Walk through the wizard: **WiFi → radio → MQTT → review**. + - **Radio**: must match the other nodes in your mesh. + - **MQTT**: set the IATA code to your **MeshMapper region code** (e.g. `YOW`), and set slot 1 to the **meshmapper** preset. +3. Click **Save & reboot**. The observer joins your Wi-Fi and connects to MeshMapper. + +### Option 2. Command Line + +Connect to the device console over USB serial (115200 baud) or by repeater login from the companion app, then run: + +```bash +set radio 910.525,62.5,7,5 # must match your mesh: ,,, +set name MyObserver +set mqtt.iata YOW # your MeshMapper region code +set wifi.ssid YourWiFiNetwork +set wifi.pwd YourWiFiPassword +set mqtt1.preset meshmapper +reboot +``` + +The IATA code must match your MeshMapper region, or your observer won't show up. After it reboots, check the connection with `get mqtt.status`. + +## Verifying Your Observer + +Once your observer is running and connected, it appears in your region's admin panel under the [Observers tab](admins.md#observers) after packets have been received (repeater or companion adverts, or wardriving pings). Its **Brokers** column shows a coloured MeshMapper badge once the broker has heard it. + +If nothing shows up, run `get wifi.status` and `get mqtt.status` on the device console, and confirm `mqtt.iata` matches your region. diff --git a/docs/mqtt-ha.md b/docs/mqtt-ha.md index 0bc4213..2446894 100644 --- a/docs/mqtt-ha.md +++ b/docs/mqtt-ha.md @@ -18,7 +18,7 @@ Select **Manage MQTT Brokers** and click **Submit**. ### 3. Add the MeshMapper Broker -Click **Add Broker** and fill in the following settings: +Click **Add Broker** and set the following. Leave everything else at its default. | Setting | Value | | --- | --- | @@ -28,18 +28,9 @@ Click **Add Broker** and fill in the following settings: | **Transport** | WebSocket | | **Use TLS** | Checked | | **Verify TLS Certificate** | Checked | -| **Keep Alive** | `60` | -| **Username** | *(leave blank)* | -| **Password** | *(leave blank)* | | **Use MeshCore Auth Token** | Checked | | **Token Audience** | `mqtt.meshmapper.net` | -| **Owner Pub Key** | *(leave blank)* | -| **Owner Email** | *(leave blank)* | -| **Payload Mode** | LetsMesh-Compatible | -| **Auth Token TTL** | `3600` | -| **Status Topic** | *(leave default)* | -| **Packet Topic** | *(leave default)* | -| **Broker IATA Code** | Your region's 3-letter IATA code (e.g., `YOW`, `SEA`, `LON`) | +| **Broker IATA Code** | Your **MeshMapper region code** (e.g. `YOW`). This must match your region, or your observer won't show up. | ### 4. Save and Exit @@ -47,4 +38,6 @@ Click **Submit**, then click **Exit** to return to the integration page. ## Verifying Your Observer -Once your observer is running and connected, it will appear in your region's **Admin Portal** under the [Observers tab](admins.md#observers) once packets have been received (repeater or companion adverts, or wardriving pings) You should see a checkmark under the broker(s) your observer is connected to. \ No newline at end of file +Once your observer is running and connected, it appears in your region's admin panel under the [Observers tab](admins.md#observers) after packets have been received (repeater or companion adverts, or wardriving pings). Its **Brokers** column shows a coloured MeshMapper badge once the broker has heard it. + +If nothing shows up, check the Home Assistant logs for MQTT errors, and confirm the Broker IATA Code matches your region. diff --git a/docs/mqtt-main.md b/docs/mqtt-main.md index 5e2f153..eb74fa9 100644 --- a/docs/mqtt-main.md +++ b/docs/mqtt-main.md @@ -1,6 +1,6 @@ # MeshMapper MQTT Setup -An **MQTT observer** is a MeshCore node that acts as the "ears" of MeshMapper. It listens for mesh traffic and publishes it to an MQTT broker, where MeshMapper picks it up for processing. A new region needs at least one online observer sending to either the **MeshMapper** or **LetsMesh** broker. MeshMapper recommends its own broker. +An **MQTT observer** is a MeshCore node that acts as the "ears" of MeshMapper. It listens for mesh traffic and publishes it to the MeshMapper MQTT broker, where MeshMapper picks it up for processing. A new region needs at least one online observer sending to the **MeshMapper broker**. ## MeshMapper Broker @@ -10,32 +10,32 @@ An **MQTT observer** is a MeshCore node that acts as the "ears" of MeshMapper. I ## MQTT Observer Methods -There are four ways to set up a MeshCore MQTT observer that collects packets and forwards them to MeshMapper. +There are four ways to set up a MeshCore MQTT observer that sends packets to MeshMapper. -### 1. MeshCore Packet Capture (Python) +### 1. MeshCore MQTT Native Firmware -This method uses a dedicated companion device (e.g., Raspberry Pi) connected to your MeshCore radio via USB, BLE, or TCP. A Python service runs continuously, capturing packets and publishing them to MQTT. +This method runs directly on the radio with no companion computer needed. The firmware captures packets and publishes them to MQTT over the board's built-in Wi-Fi. Most ESP-based devices with Wi-Fi are supported. - - **Requires**: A Raspberry Pi or similar always-on Linux computer, plus a MeshCore radio connected via USB or BLE - - **Best for**: Dedicated observer setups where you have a spare device to run the capture service - - **Guide**: [MeshCore Packet Capture Setup](mqtt-python.md) + - **Requires**: An ESP-based device with Wi-Fi + - **Best for**: The simplest hardware setup, since no secondary computer is needed + - **Guide**: [MeshCore MQTT Native Firmware Setup](mqtt-firmware.md) + - **Built by**: HerculesMulligan ### 2. MeshCore Home Assistant Integration -If you already run Home Assistant, this is the easiest route. The MeshCore-HA integration connects to your radio via USB, Wi-Fi, or Bluetooth and forwards packets to MQTT, while also exposing mesh data as HA entities for monitoring and automation. +The MeshCore-HA integration connects to your radio via USB, Wi-Fi, or Bluetooth and forwards packets to MQTT, while also exposing mesh data as HA entities for monitoring and automation. - **Requires**: A Home Assistant instance with a MeshCore radio accessible via USB, Wi-Fi, or Bluetooth - **Best for**: Users who already have Home Assistant and want observer functionality alongside mesh monitoring and automation - **Guide**: [MeshCore Home Assistant Setup](mqtt-ha.md) -### 3. MeshCore MQTT Native Firmware - -This method runs directly on a Heltec V3 or V4 board with no companion device needed. The firmware natively captures packets and publishes them to MQTT using the board's built-in Wi-Fi. +### 3. meshcoretomqtt (Python) - - **Requires**: A Heltec V3 or V4 with the MQTT-enabled firmware flashed - - **Best for**: The simplest hardware setup, since no secondary computer is needed +This method uses an always-on computer (e.g., Raspberry Pi) connected to a MeshCore repeater by USB. A Python service runs continuously, capturing packets and publishing them to MQTT. It includes a built-in MeshMapper broker preset. -Flash the observer firmware from the [MeshCore observer flasher](https://observer.gessaman.com/), built by agessaman/HerculesMulligan. It runs in your browser and walks you through flashing and setup. The source is in [agessaman/MeshCore](https://github.com/agessaman/MeshCore/tree/mqtt-bridge-implementation). + - **Requires**: A Raspberry Pi or similar always-on Linux/macOS computer, plus a MeshCore repeater with packet logging enabled, connected by USB + - **Best for**: Dedicated observer setups where you have a spare computer and repeater + - **Guide**: [meshcoretomqtt Setup](mqtt-python.md) ### 4. PyMC @@ -45,12 +45,12 @@ This method uses the PyMC software, which handles MQTT configuration directly fr - **Best for**: Anyone already running a PyMC repeater - **Guide**: [PyMC Repeater MQTT Setup](mqtt-pymc.md) -## Common observer questions +## Common Observer Questions -**Should I send to MeshMapper, LetsMesh or both?** Either broker can supply reports for MeshMapper. You may publish to both; MeshMapper combines reports from its configured brokers. One working broker is enough for onboarding. +**Which broker should I send to?** The MeshMapper broker. MeshMapper also collects from LetsMesh, but that isn't our infrastructure, so we can't guarantee we'll always have access to it. **Can I use a mobile observer?** It can submit reports while online, but a fixed, always-on observer is a better choice for a region's required listener. A mobile receiver cannot verify a new region while it is offline or away from that region. -**Why is my observer not listed?** A broker connection by itself is not an observer report. Check that it publishes `status` or `packets` on the `meshcore///...` topic, using the region's code. Then check the region admin panel's **Observers** tab and the broker checkmarks. Allow time for the first report to arrive. +**Why is my observer not listed?** A broker connection by itself is not an observer report. Check that it publishes `status` or `packets` on the `meshcore///...` topic, using the region's code. Then check the region admin panel's **Observers** tab and its **Brokers** badges. Allow time for the first report to arrive. -**Can I run a regional MQTT broker?** A region admin can register a broker in **Settings**. Provide a reachable host and port, WebSockets transport, and its required authentication credentials. MeshMapper subscribes only to that region's topics; see [Observer verification](mqtt-pymc.md#verifying-your-observer) after saving. Do not publish broker credentials in a public channel. +**Can my region use its own MQTT broker?** Yes. After onboarding, region admins can configure MeshMapper to also pull from their own regional broker in the admin panel under **Settings → MQTT Brokers & Observers**. Provide a reachable host and port, WebSockets transport, and its authentication credentials. MeshMapper subscribes only to that region's topics. Do not publish broker credentials in a public channel. diff --git a/docs/mqtt-pymc.md b/docs/mqtt-pymc.md index 1fa14ac..07a72c6 100644 --- a/docs/mqtt-pymc.md +++ b/docs/mqtt-pymc.md @@ -30,6 +30,8 @@ This is the easiest way to add MeshMapper to an existing pyMC-Repeater installat ![Restarting pyMC-Repeater from the terminal](assets/pymc-mqtt3.png) +Make sure `iata_code` in your pyMC config is set to your **MeshMapper region code**, or your observer won't show up. + ### Option 2. Add MeshMapper manually If you prefer, you can still add MeshMapper by editing the config file directly. @@ -48,11 +50,11 @@ Open the pyMC-Repeater config file: sudo nano /etc/pymc_repeater/config.yaml ``` -Add `mqtt.meshmapper.net` to the `brokers` field under the `brokers` section: +Under `mqtt:` → `brokers:`, add the MeshMapper entry below. If you already have other brokers listed, add this as another item in the list; don't replace them. Set `iata_code` to your **MeshMapper region code**, or your observer won't show up. ```yaml mqtt: - iata_code: # e.g., "SFO", "LHR", "Test" + iata_code: # your MeshMapper region code, e.g. "YOW" status_interval: 300 # How often a status message is sent (in seconds) owner: "" email: "" @@ -62,7 +64,7 @@ mqtt: transport: websockets host: mqtt.meshmapper.net port: 443 - format: letsmesh + format: letsmesh # packet format, leave as-is disallowed_packet_types: [] retain_status: false tls: @@ -90,6 +92,6 @@ sudo journalctl -u pymc-repeater.service -f | grep MeshMapper ## Verifying Your Observer -Once your observer is running and connected, it will appear in your region's **Admin Portal** under the [Observers tab](admins.md#observers) once packets have been received (repeater or companion adverts, or wardriving pings). You should see a checkmark under the broker(s) your observer is connected to. +Once your observer is running and connected, it appears in your region's admin panel under the [Observers tab](admins.md#observers) after packets have been received (repeater or companion adverts, or wardriving pings). Its **Brokers** column shows a coloured MeshMapper badge once the broker has heard it. -If PyMC says it is connected but MeshMapper shows no data, check PyMC's service logs for MQTT errors, then confirm the broker host, WebSockets, TLS and MeshCore token settings above. Confirm its IATA code matches the region and that it is publishing `status` or `packets`. An observer may appear before any repeater does: repeaters need a valid name and an advert received by an observer, and a region may hold new repeaters in **Pending** until an admin approves them. +If nothing shows up, check the logs (`sudo journalctl -u pymc-repeater.service -f`) for MQTT errors, and confirm `iata_code` matches your region. diff --git a/docs/mqtt-python.md b/docs/mqtt-python.md index da234b0..b5a1ed6 100644 --- a/docs/mqtt-python.md +++ b/docs/mqtt-python.md @@ -1,145 +1,55 @@ -# MeshCore Packet Capture +# meshcoretomqtt (Python) -These instructions are for the community [meshcore-packet-capture](https://github.com/agessaman/meshcore-packet-capture) project from agessaman/HerculesMulligan. +These instructions cover setting up the community [meshcoretomqtt](https://github.com/Cisien/meshcoretomqtt) project from Cisien as a MeshMapper observer. It runs on an always-on computer connected to a MeshCore repeater by USB, and has a built-in **MeshMapper** broker preset. ## Prerequisites - - A MeshCore-compatible device (e.g., T1000e, Heltec, T-Beam) to act as your observer node - - A Raspberry Pi, Linux server, or similar always-on computer running a Debian-based OS (Raspberry Pi OS, Ubuntu, etc.) - - A USB cable (for serial connection) or Bluetooth support (for BLE connection) - - Internet access for packet forwarding + - A Raspberry Pi (Zero 2, 3 or 4 recommended) or similar always-on Linux or macOS computer + - A MeshCore repeater connected by USB, flashed with packet logging enabled (build flag `-D MESH_PACKET_LOGGING=1`) and firmware v1.8.0 or later + - The repeater configured with a unique name + - Internet access ## Installation -### 1. Flash a Companion Device - -Configure a Companion device using the [MeshCore Flasher Tool](https://flasher.meshcore.co.uk) and connect it to your Raspberry Pi or Linux server via USB. Ensure radio settings are correct for your region. - -### 2. Install Dependencies +### 1. Run the Installer ```bash -sudo apt update -sudo apt install -y python3 python3.12-venv curl git +curl -fsSL https://raw.githubusercontent.com/Cisien/meshcoretomqtt/main/install.sh | sudo bash ``` -### 3. Install the MeshCore Decoder - -The MeshCore decoder is required for authentication when sending packets to the broker: - -```bash -curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash -source ~/.bashrc -nvm install --lts -npm install -g @michaelhart/meshcore-decoder -``` +The installer sets up everything (Python environment, a system service, and config at `/etc/mctomqtt/`) and walks you through configuration. When a prompt shows a value in brackets, pressing Enter uses it. -Verify the installation: +### 2. Answer the Prompts -```bash -which meshcore-decoder -``` + - **Installation method**: choose **1) System service** (recommended). + - **Serial device**: pick the USB port your repeater is connected to. + - **IATA code**: enter your **MeshMapper region code** (e.g. `YOW`). This must match your region, or your observer won't show up. + - **MQTT Broker Configuration**: choose **1) Select bundled broker presets**, then select **meshmapper**. Choose **5) Finish** when done. -### 4. Run the meshcore-packet-capture Installer +### 3. Check It's Running ```bash -bash <(curl -fsSL https://raw.githubusercontent.com/agessaman/meshcore-packet-capture/main/install.sh) +sudo systemctl status mctomqtt # Check status +sudo journalctl -u mctomqtt -f # View live logs ``` -The interactive installer will walk you through the remaining configuration steps below. - -### 5. Device Connection - -You will be prompted to select a connection type: - -| Method | Best For | Notes | -| --- | --- | --- | -| **Serial** (recommended) | USB-connected devices | Most reliable for continuous operation | -| **BLE** | T1000e and compatible devices | Wireless, no cable needed | -| **TCP** | Network-connected devices | For use with ser2net or TCP-to-serial bridges | - -For serial connections, the script will automatically detect connected devices. Select your device from the list. - -### 6. IATA Code - -Enter your region's **3-letter IATA code** (e.g., `SEA`, `LAX`, `YOW`, `LON`). This identifies which MeshMapper region your observer belongs to. - -Use the code of the region that should receive the observer's reports. MQTT topics carry this code, and MeshMapper's subscriber uses it when choosing a region. If your receiver covers several regions, coordinate with their admins rather than assuming one code will place the same report in every region. - -### 7. Owner Information (Optional) - -You may optionally configure: - - - **Owner Public Key**: The public key of the observer owner (64 hex characters) - - **Owner Email**: A contact email - -MeshMapper doesn't use these, so you can skip them. +## Changing the Configuration -### 8. MQTT Broker Configuration - -The script will ask whether to enable the LetsMesh Packet Analyzer. MeshMapper doesn't need it, so that's up to you. - -When prompted to configure additional brokers, select "1" additional, and add the MeshMapper broker with the following settings: - -| Setting | Value | -| --- | --- | -| Server hostname | `mqtt.meshmapper.net` | -| Port | `443` | -| WebSockets transport | **Yes** | -| TLS/SSL encryption | **Yes** | -| Verify TLS certificates | **Yes** | -| Authentication method | **MeshCore Auth Token** | -| Token audience | `mqtt.meshmapper.net` | - -When prompted for topic configuration, select **Default pattern** (`meshcore/{IATA}/{PUBLIC_KEY}/status`, `meshcore/{IATA}/{PUBLIC_KEY}/packets`). - -### 9. Installation Method - -Choose how the capture software should run: - -| Method | Description | -| --- | --- | -| **System Service** (recommended) | Runs on boot via systemd, auto-restarts on failure | -| **Docker Container** | Isolated environment, easy to update | -| **Manual** | No automatic startup, run when needed | - -For the recommended **systemd service**, the script will: - - - Install and enable the service - - Start it immediately - - Verify a successful MQTT connection - -## Managing the Service - -Once installed as a systemd service, use these commands: +Your settings are in `/etc/mctomqtt/config.d/99-user.toml` and the MeshMapper preset in `/etc/mctomqtt/config.d/10-meshmapper.toml`. Don't edit `/etc/mctomqtt/config.toml`, as it's overwritten on updates. ```bash -# Start / stop / restart -sudo systemctl start meshcore-capture -sudo systemctl stop meshcore-capture -sudo systemctl restart meshcore-capture - -# Check status -sudo systemctl status meshcore-capture - -# View live logs -sudo journalctl -u meshcore-capture -f +sudo nano /etc/mctomqtt/config.d/99-user.toml +sudo systemctl restart mctomqtt ``` -The configuration file is stored at: +## Updating -``` -~/.meshcore-packet-capture/.env.local +```bash +curl -fsSL https://raw.githubusercontent.com/Cisien/meshcoretomqtt/main/scripts/update.sh | sudo bash ``` -## Resource Limits - -The systemd service includes built-in safeguards: - - - **Memory**: 512 MB limit - - **CPU**: 50% limit - - **Tasks**: 200 max - - **Auto-restart**: Up to 3 failures within 5 minutes before stopping - ## Verifying Your Observer -Once your observer is running and connected, it will appear in your region's **Admin Portal** under the [Observers tab](admins.md#observers) once packets have been received (repeater or companion adverts, or wardriving pings) You should see a checkmark under the broker(s) your observer is connected to. +Once your observer is running and connected, it appears in your region's admin panel under the [Observers tab](admins.md#observers) after packets have been received (repeater or companion adverts, or wardriving pings). Its **Brokers** column shows a coloured MeshMapper badge once the broker has heard it. + +If nothing shows up, check the logs (`sudo journalctl -u mctomqtt -f`) for MQTT errors, and confirm the IATA code matches your region. diff --git a/docs/multibyte.md b/docs/multibyte.md index a817d29..a64e2a0 100644 --- a/docs/multibyte.md +++ b/docs/multibyte.md @@ -1,79 +1,91 @@ # Multi-Byte Repeaters -Every packet that travels through a MeshCore mesh network carries a record of its journey — a list of the repeaters it passed through. Each repeater stamps the packet with the prefix of its Public ID, called a **hop**. +Every packet in a MeshCore mesh carries a record of the repeaters it passed through (its **path**). Each repeater adds the first 1, 2 or 3 bytes of its Public ID to the path. Each of those entries is a **hop**. -MeshMapper fully supports multi-byte hops in the wardriving app, the map, and packet analyzer. +MeshMapper supports 1-, 2- and 3-byte hops across the wardriving app and the map. --- ## The 1-Byte Problem -In 1-byte mode, repeaters are identified by just the first two hex characters of their Public ID (e.g., `A1`, `4F`, `09`). With only **254 possible combinations** (hex `01` to `FE` — `00` and `FF` are reserved by MeshCore firmware), growing regions inevitably see two different repeaters sharing the same ID. +In 1-byte mode, a repeater is identified by just the first two hex characters of its Public ID (e.g. `A1`, `4F`, `09`). That's only **254** usable IDs (`00` and `FF` are reserved), so growing regions end up with two repeaters sharing an ID. -When this happens, MeshMapper can't tell which physical repeater was actually involved in a packet's path. It enters a quarantine mode for the affected devices to protect data integrity. +When that happens, MeshMapper can't tell which repeater a packet went through. The affected repeater is marked **Ambiguous** (red on the map). Pings still count for coverage, but they aren't linked to it. -!!! tip "Learn More About Collisions" - For a detailed explanation of how MeshMapper detects, handles, and resolves duplicate repeater IDs, see [Duplicate Repeater IDs](duplicaterepeaterid.md). +With 2 or 3 bytes there are tens of thousands or millions of IDs, so collisions become rare. + +!!! tip "How MeshMapper decides" + A repeater is judged at its own width, and a hop is only credited when exactly one repeater matches it. See [The Rules](duplicaterepeaterid.md#the-rules) on the Duplicate Repeater IDs page. ## Upgrading to Multi-Byte -Upgrading a region from 1-byte to multi-byte hops is a gradual process — you don't need to update every device at once. Repeaters upgraded to the latest multi-byte capable firmware will still relay packets from repeaters and companions running older 1-byte firmware. +You don't need to upgrade every device at once. Multi-byte repeaters still relay packets from repeaters and companions on 1-byte firmware. + +### Step 1: Update the Repeater -### Step 1: Update Firmware +Flash the repeater with **MeshCore firmware v1.14.1 or newer**, then set its hop width from the repeater's command line. -Flash repeaters and companion devices with **MeshCore firmware v1.14.1 or newer**. The firmware's hop byte configuration must be set to 2 or 3 bytes. +For 2-byte: -In the command line console on the repeater, for 2-byte, set: ``` set path.hash.mode 1 ``` -and for 3-byte: + +For 3-byte: + ``` set path.hash.mode 2 ``` -When done, reboot the device, then **send a flood advert**. This will "upgrade" the repeater in MeshMapper to multi-byte capable automatically. +Reboot the repeater, then **send a flood advert**. MeshMapper reads the width from the repeater's flood advert and updates it automatically. -Repeaters and companions in the region should be running the same configuration. +### Step 2: Set the Width for Wardrivers -### Step 2: Update Region Settings +Once most of your repeaters are upgraded, set **App Path Bytes** in the region admin panel under **Settings → Wardriving → Radio Channels** (the **Path B** column, one per radio preset). Options are **Device** (leave it to the wardriver's radio), **2** or **3**. -When the majority of a regions repeaters have been upgraded to a multi-byte capable firmware, in the region's admin panel, go to **Settings** and set the **Hop Bytes** value to match your regions configuration. Changing this value triggers an automatic collision recalculation across all repeaters in the region. (You must be an administrator of your region in order to access this setting) +This tells the wardriving app what hop width to set on wardrivers' companion radios. It doesn't change repeaters; they get their width from their own adverts. For grouped regions, the group admin sets it. -### Step 3: Automatic Detection and Upgrade +### How MeshMapper Tracks Each Repeater -As updated repeaters relay packets, MeshMapper detects the longer hop IDs automatically. It tracks hop bytes **per repeater** — so each device's byte length updates individually as it's heard on the network. +MeshMapper tracks every repeater separately, so a region can run a mix of 1-, 2- and 3-byte repeaters. -For example, if repeater `A1B2C3D4E5F6` was previously known as a 1-byte device (hop ID `A1`), the first time it's heard with a 2-byte hop (`A1B2`), MeshMapper updates its record. No manual intervention needed. + - **Advertised width**: taken from the repeater's latest **flood advert**. If it later adverts at 1 byte again, this goes back down. + - **Multibyte capable**: set the first time MeshMapper sees the repeater with a 2- or 3-byte hop, in its own advert, a wardriving ping, or any flood packet an observer hears. Once set, it stays set. -!!! note "Mixed Environments" - During a transition period, a region may have a mix of 1-byte and 2/3-byte repeaters. MeshMapper handles this gracefully — it uses each repeater's individually tracked hop byte value for collision detection and path resolution. Two repeaters that collide at 1 byte may be perfectly distinguishable at 2 bytes. +For example, repeater `A1B2C3D4E5F6` was known as `A1`. The first time it's heard as `A1B2`, it's marked multibyte capable and judged at 2 bytes from then on. -!!! note "Packet Types" - Not all packet types are ingested into the MeshMapper engine responsible for processing repeater upgrades. In order for a repeater to automatically upgrade to 2 or 3-byte capable within MeshMapper, its ID must be contained within the path of an **advert** or **wardriving** packet. Public messages or other packet types (trace, request, etc.) will not result in an automatic upgrade. +### Collisions Clear Up Automatically -### Smart Collision Resolution +As repeaters upgrade, old collisions resolve on their own: -As repeaters upgrade, collisions that existed in 1-byte mode may automatically resolve: + - `AB` (1-byte) and `AB` (1-byte) **collide**: they can't be told apart. + - `AB12` (2-byte) and `AB9F` (2-byte) **don't**: the longer IDs tell them apart. -- Repeater `AB` (1-byte) and repeater `AB` (1-byte) **are** in collision — indistinguishable. -- After upgrading, repeater `AB12` (2-byte) and repeater `AB9F` (2-byte) are **no longer** in collision — the longer IDs differentiate them. +When a repeater in a collision next adverts, MeshMapper re-checks it and returns it to normal if it can now be told apart. -MeshMapper re-evaluates collisions as hop bytes update, restoring previously excluded repeaters to active status when they become distinguishable. +## Tracking Your Region's Upgrade -### Filtering by Hop Bytes - -The map's **Filter Map Data** panel includes a **Hops away** filter, allowing you to view only repeaters of a specific byte length. This is helpful for tracking firmware upgrade progress across your region — quickly see which repeaters are still running 1-byte firmware and need updating. In addition, the **Repeater List** (Region menu) splits repeaters into **Non-Multibyte Capable** and **Multibyte Capable** tabs, based on whether each repeater has been observed advertising or processing a multibyte ID. + - **Repeater List** (**Region** menu): the **Non-Multibyte Capable** and **Multibyte Capable** tabs show which repeaters still need upgrading. + - **ID width** filter (**Filter Map Data**): show only repeaters and pings using 1-, 2- or 3-byte IDs. See [Filters](layers.md#filters). + - **Multibyte Upgrade Board** on the global leaderboard: ranks regions by how far their upgrade has got. ### Repeater ID Grid -The Repeater ID Grid (found in **Region Info > Repeater List**) provides a visual overview of first-byte ID usage across the region. Each cell represents a possible first-byte prefix (`00` to `FF`) and is colour-coded: +Open **Region → Repeater IDs** to see **Repeater ID Usage**: a grid of every first-byte prefix (`00` to `FF`). | Colour | Status | Meaning | | --- | --- | --- | -| **Green** | Available | No repeater is using this ID in any form. | -| **Blue** | Deployed | ID is in use with no conflicts — a single 1-byte repeater, a single multi-byte repeater, or multiple unique multi-byte repeaters sharing the same first byte. | -| **Red** | Conflict | A 1-byte repeater shares this first byte with one or more multi-byte repeaters. This is ambiguous for legacy clients that only see the first byte. | -| **Black** | Reserved | Reserved by MeshCore firmware (`00` and `FF`). Not available for assignment. | +| **Green** | Available | No repeater uses this first byte. | +| **Blue** | Deployed | In use, and every repeater here can be told apart. | +| **Red** | Conflict | At least one repeater here can't be told apart from another: two 1-byte repeaters sharing it, or multi-byte repeaters sharing their full 2 or 3 bytes. | +| **Dark grey** | Reserved | `00` and `FF`, reserved by MeshCore. | + +Click a cell to see the repeaters using that prefix, with their Public ID, width, hardware and any conflict. Use the **search** box or the tag filters (**MB**, **Ambiguous**, **2-Byte**, **3-Byte**, **No Location**, **Out of Region**, **Ghost**, **Observer**, **CARpeater**) to narrow it down. + +Private (🚫) repeaters are listed as **Hidden** and still count towards usage and conflicts. + +## In the Wardriving App -Clicking any cell shows the repeater(s) assigned to that prefix, including their Public ID and byte mode. \ No newline at end of file + - If the region sets **App Path Bytes**, the app sets that width on your companion radio and tells you when it changes. + - If the region leaves it to the device, you can choose the width yourself in the app's wardriving settings. + - Companion firmware older than 1.14 can only use 1 byte; the app will recommend a firmware update. diff --git a/docs/multiregions.md b/docs/multiregions.md index 52a5880..ab0f33c 100644 --- a/docs/multiregions.md +++ b/docs/multiregions.md @@ -1,51 +1,45 @@ # Multiregion Groups -A Multiregion Group allows multiple individual regions/IATA's to be combined into a single, seamless map interface, and allows MeshMapper to properly represent data based on real-world conditions. +A Multiregion Group combines several neighboring regions into one map, so MeshMapper can correctly handle mesh traffic that crosses region borders. ## How it Works When regions are grouped: -1. **Unified Map**: The individual maps and leaderboards for each region are effectively merged. +1. **Unified Map**: The individual maps for each region are merged. 2. **Shared Logic**: The system treats the group as a single entity for data processing. - * **Duplicate Detection**: Scans for duplicate repeater IDs across *all* regions in the group. If region `AAA` has a repeater `AA` and region `BBB` has a repeater `AA`, those repeaters will correctly enter collision with one another. - * **Leaderboards**: Statistics are aggregated. A user's contribution counts towards the group leaderboard, and repeaters are ranked against all others in the group. -3. **Centralized Administration**: Administrators can gain access to a **Grouped Admin Panel**, allowing them to monitor and manage all sub-regions simultaneously. Individual regions within the group can still be administered individually. -4. **Wardriving Handoff**: Wardrivers leaving one individual region and entering another will have their session automatically transferred and companion authorized without interruption. + * **Duplicate Detection**: Scans for duplicate repeater IDs across *all* regions in the group. If region `AAA` has a repeater `AA` and region `BBB` has a repeater `AA`, they are correctly flagged as duplicates of each other. + * **Leaderboards**: Statistics are combined. A user's contributions count towards the group leaderboard, and repeaters are ranked against all others in the group. +3. **Centralized Administration**: Administrators can use a **Grouped Admin Panel** to monitor and manage every region in the group. Each region can still be administered on its own. -## When to use a Multiregion Group +## When to Use a Multiregion Group -Multiregion groups are designed for specific scenarios where one regions mesh traffic can be heard by another. +Multiregion groups are designed for specific scenarios where one region's mesh traffic can be heard by another. -### ✅ When to use multiregion groups +### ✅ When to Use a Group * When repeaters in one region can be heard by observers in a neighboring region. * When wardriving in one region may have pings heard/repeated by repeaters in a neighboring region. -### ❌ When NOT to use it +### ❌ When Not to Use a Group * When repeater adverts or wardriving traffic in one region would not be heard by repeaters or observers in another. Combining two regions that cannot physically share mesh traffic can result in repeaters unnecessarily entering a collision/duplicate state. ## Why? -The primary reason to create multiregion groups is **data accuracy**. Use this example below: +The primary reason to create multiregion groups is **data accuracy**. For example: -![Image](https://meshmapper.net/img/upload_20260223_081630_ea15ff3e.jpg) +![A wardriver near the border of region AAA is repeated by region BBB's repeater AA. Not grouped, the ping is linked to AAA's AA. Grouped as CCC, it is linked to neither.](assets/multiregion-duplicate-ids.svg) -In this example, you have a car wardriving around the border of region `AAA`. Nearby is region `BBB`. +A wardriver near the border of region `AAA` sends a ping. Region `AAA`'s repeater `AA` is too far away to hear it, but region `BBB`'s repeater `AA` is close enough and repeats it. MeshMapper sees a successful round trip through a repeater with ID `AA`. -The wardrivers companion sends out a ping. Region `AAA`'s repeater `AA` is too far away to hear the ping. Region `BBB`'s repeater `AA` is close enough and rebroadcasts that ping. The wardrivers companion hears this repeat. The ping propagates through the mesh network is is picked up by an observer in region `AAA`. MeshMapper's backend processes both data points and determines successful bidirectional communication... +* ❌ **Not grouped**: `AAA` only knows about its own `AA`, so it links the ping to the wrong repeater. +* ✅ **Grouped**: MeshMapper knows both regions have an `AA`, so the ping still counts for coverage but isn't linked to either. Select the ping on the map to see **Duplicate** lines to each possible repeater, and open it to see the candidates with their signal info. -* ❌ **When the regions ARE NOT grouped**: ...but incorrectly associates it with region `AAA`'s repeater `AA` (it is the only `AA` it knows of). A link from that grid square to the incorrect repeater is made. -* ✅ **When the regions ARE grouped**: ...however, it is aware of two repeaters sharing the ID of `AA`. Associations ARE NOT made to either repeater as the data is ambiguous. The map will draw suggestion lines from that grid square to both repeaters and provide signal strength information, which may allow the viewer to make a reasonable assumption on their own as to which repeater was actually involved. +This mainly affects repeaters using 1-byte IDs. Repeaters using [multi-byte IDs](multibyte.md) are usually told apart even when their first byte matches. ## Administration -Managing a multiregion group is similar to managing a single region, with added capabilities. - -### Grouped Admin Panel -Administrators can view data for the entire group or filter by specific sub-regions. -* **Global Actions**: Tools like "Replace Repeater" or "Bulk Update" can apply to the entire group. -* **Notes**: Adding a note to a repeater or companion (e.g., "Tom owns this repeater") makes that note visible to all admins in the group, regardless of which specific region the repeater belongs to. +Managing a multiregion group is similar to managing a single region. In the grouped admin panel, tools like "Replace Repeater" and "Bulk Update" apply to every region in the group. ## Requesting a Multiregion Group -As each region in a multiregion group still maintains its own backend databases, regions can be added or removed from multiregion groups easily. Please reach out to a [Global Administrator](https://wiki.meshmapper.net/administratorlist/) to start the process. \ No newline at end of file +Each region in a group keeps its own data, so regions can easily be added to or removed from a group. Please reach out to a [Global Administrator](administratorlist.md) to start the process. \ No newline at end of file diff --git a/docs/onboarding.md b/docs/onboarding.md index cf4ba56..61f216b 100755 --- a/docs/onboarding.md +++ b/docs/onboarding.md @@ -1,86 +1,86 @@ # Onboarding a New Region -MeshMapper is designed to be scalable, allowing new geographic regions to be added to the network. This guide outlines the process for community members to request a new map zone for their local mesh. +This guide walks through requesting a new MeshMapper region for your local mesh. -*Please note that all region approvals are granted at the discretion of the master and global administration team. Some circumstances may better be served by working with an existing region rather than creating a new one.* +*All region approvals are at the discretion of the MeshMapper administration team. Sometimes working with an existing region is a better fit than creating a new one.* -## Prerequisites +## Before You Start -Before requesting a new region, you must ensure the local infrastructure is ready to support it and that the new region would not be redundant or better served by making modifications to an existing region's boundaries. + - **No existing region**: Your area must not already be substantially covered by another region. Regions within regions are not allowed. + - **No nearby neighbor that could expand**: If a nearby region could reasonably be expanded to cover your area, that's preferred. A new region makes sense when your mesh is clearly separate (e.g. distance or terrain that blocks RF). If that's your case, explain why in **Additional Notes**. + - **An MQTT observer**: You need at least one (preferably 2-3) observer nodes online in your area, connected to the **MeshMapper MQTT broker**. Observers are the "ears" of the map. See [MeshMapper MQTT Setup](mqtt-main.md). - - **No Existing Region**: There must not be an existing region covering a substantial portion of the area desired for any new region. Regions within regions will not be allowed. - - **No Nearby Neighbors**: No nearby neighboring regions should exist that could reasonably be expanded to include your desired area. The details matter. If your mesh is and will likely remain distinct from a nearby neighbor (e.g. due to extreme distance or natural terrain features that block RF), then a new region would be reasonable. If your desired new region falls in this category, please explain how it is justified vs modifying a nearby existing region's boundaries in the "Additional Notes" field. - - **MQTT Observers**: You need at least one (preferably 2-3) nodes configured as **MQTT Clients** connected to the **MeshMapper** broker, the **LetsMesh** broker, or both. - - These nodes act as the "ears" of the map, reporting traffic to MeshMapper. - - See [MeshMapper MQTT Setup](mqtt-main.md) for detailed instructions. +## Starting a Request -## The Onboarding Form +Open the onboarding form from [meshmapper.net](https://meshmapper.net): -To start the process, open the **Region Onboarding** form — available from the [meshmapper.net](https://meshmapper.net) homepage, or from any region map via the **About** menu → **Onboard Your Region**. + - **Switch Region** menu → **Onboard Region**, or + - **About** menu → **Onboard Your Region**, or + - go directly to [meshmapper.net/?onboarding](https://meshmapper.net/?onboarding). -The form collects the following critical information: +The form walks you through five steps: **Code → Region → Boundary → Mesh → Submit**. -| Field | Description | -| --- | --- | -| **IATA Code** | The 3-letter code that will identify your region in the database and URL (e.g., `yow.meshmapper.net`). *Please note that the mere existence of an IATA code does not, in and of itself, imply suitability for a MeshMapper region to be created using that code. International and regional commercial airports are strongly preferred over military or general aviation airfields.*| -| **Region Name** | The display name for the map (e.g., "Ottawa, CA", "London, UK"). | -| **Region Radius** | A rough estimate (in km) of the area you intend to cover. | -| **Region Boundary** | This is where you define your desired region boundary. We strongly encourage region admins to use geoJSON files and coordinate with neighboring regions when defining a region's boundaries. More information and geoJSON resources are available at [Region Boundaries](region_boundaries.md). | -| **Email Address / Discord Notifications** | Enter your email address (required) and optionally - though encouraged - link your Discord account to receive notifications on the status of your application. | -| **Additional Notes** | Use this field to provide additional details or context about your application. If your desired region doesn't meet the [prerequisites](#prerequisites) above and you believe an exception should be made, justify it in detail here. | -| **Public Channels** | A list of public channels used in your mesh (e.g., `Chat`, `Emergency`). This helps the wardriving app correctly identify valid traffic. | -| **Volunteer as Administrator** | Optional but recommended. Tick this to volunteer as your region's administrator. See [below](#volunteer-as-region-administrator) for details. | +## 1. Code -## Volunteer as Region Administrator +Search for your city, airport, or code and pick your region's **IATA airport code**. It becomes your region's address (e.g. `yow.meshmapper.net`). Codes already in use are greyed out, and nearby available codes are suggested. + +*Having an IATA code doesn't by itself make it suitable for a region. International and regional commercial airports are strongly preferred over military or general aviation airfields. The airport must also be reasonably close to your region.* + +## 2. Region + +Confirm the **Country** and **Region Name** (filled in from the airport you picked). The name is what people see in the region list, e.g. "Ottawa, CA". -The onboarding form includes an optional **Volunteer as Region Administrator** checkbox. +## 3. Boundary -Enabling this option signals to the MeshMapper team that you are willing to take on the administrator role for your new region. As a region administrator, you would be responsible for: +MeshMapper builds your boundary from OpenStreetMap borders. - - Monitoring and managing your region's data and settings. - - Supporting local wardrivers and answering questions about the map. - - Being an active and available point of contact for your mesh community. - - **Please note: Admins are expected to maintain an ongoing, active presence beyond the initial onboarding process. Admins who do not login to their account on the MeshMapper admin panel for more than 90 days are subject to being marked as inactive and/or having admin access removed.** Inactive accounts will not be consulted on changes to a region, and new admins may be added to a region at any time should no active admin accounts be present. + 1. **Drag the pin** onto your region. Picking a code moves the map, but not the pin, so make sure you drag it. + 2. The borders around the pin load automatically (or press **Load Boundary**). Choose a level: **State/Prov**, **County** (default), or **Local** (municipality, where available). + 3. **Click the green areas** you want to include. Use the arrow buttons around the pin to load more areas. + 4. Press **Continue** to merge your selection into one boundary. -**Requirements:** +On the map, **purple** is existing regions, **green** is areas you can pick, and **cyan** is your selection. Areas that belong to another region can't be picked, and your boundary can't overlap an existing region. - - Provide an email address. Linking Discord is optional and lets you receive the invite by DM instead of email. - - You must be genuinely active in your local mesh community. +*Keep the boundary reasonable and coordinate with neighboring regions. It can be changed later as your network grows.* -**What happens if you volunteer:** +!!! note "Custom boundaries" + Drawing or importing your own GeoJSON (under **Advanced Mapping**) is only accepted in special circumstances. If you think you need one, explain why in **Additional Notes**. See [Region Boundaries](region_boundaries.md). -When your region is approved, MeshMapper grants this region to your existing unified account or sends an invite bound to your email or linked Discord account. Open the invite, sign in or create your MeshMapper account, and accept it. The same account signs in to the portal and your region's admin panel. No generated admin key is sent. +## 4. Mesh -## Defining the Boundary +**Public Channels**: List any public channels your mesh uses besides `#public` (e.g. `Chat`, `Emergency`). The app listens on these channels while wardriving, so more channels means more packets get decoded and verified. -One of the most important steps is defining the geographic boundary of your region. For a more detailed look into creating region boundaries (particularly if using geoJSON files), please see [Region Boundaries](region_boundaries.md). Regardless of which method is ultimately used, look at the other regions in your area and attempt to coordinate/align with area best practices. +**Regions/Scopes**: We highly recommend your area scope its wardriving traffic. However, if scopes aren't set up on the repeaters in your mesh, every ping will show as a drop. - - **The Map Tool**: The form includes an interactive map with drawing tools. - - **Import GeoJSON (strongly preferred)**: Click the **Import GeoJSON** button to paste GeoJSON data directly. This is useful if you already have a boundary defined in another tool (e.g., [geojson.io](https://geojson.io)). Supported formats include `Polygon`, `MultiPolygon`, `Feature`, and `FeatureCollection`. Drag the pin to your desired load-in view when loading the region on the web. - - **Draw Polygon (alternate preferred)**: Use the **Polygon Tool** (pentagon icon) to draw a precise shape around your mesh's coverage area if a circle doesn't accurately describe it. Alternatively, click the "Auto Generate Boundry" button to have AI attempt to draw the boundry for you. Drag the pin to your desired load-in view when loading the region on the web. - - **Radius Around Region Center (discouraged)**: Drag the pin or enter the GPS coordinates (degrees longitude west are negative numbers) and desired radius (in km) in the fields above the map, or drag the pin to your desired center point and then set the radius. This will generate a circular region around the pin. - - **Purpose**: This polygon is used to: - - Define where wardriving activities in your region can occur. - - Determine if a user is "In Zone" for authentication purposes. - - Render the region border on the global map. +## 5. Submit + + - **E-Mail Address** (required). + - **Link Discord** (optional, recommended): get status updates and region alerts by Discord DM. + - **Volunteer as Region Administrator** (optional, recommended): see [below](#volunteer-as-region-administrator). + - **Additional Notes**: anything the team should know, including why an exception to the [prerequisites](#before-you-start) should be made. + +## Volunteer as Region Administrator -*Note: Keep the boundary reasonable. You can always modify it later, in coordination with your neighbors, as your network grows.* +Tick **Volunteer as Region Administrator** to become your region's admin. Admins: -## Submission & Approval + - manage their region's data and settings, + - support local wardrivers and answer questions about the map, + - are an active point of contact for their mesh community. -Once you submit the form: +You must be genuinely active in your local mesh community. Once you accept, you're listed publicly as an admin on your region's map. - - 1. **MQTT Verification**: MeshMapper servers will verify if MQTT-connected observers are sending data to the brokers at either letsmesh.net or MeshMapper (or both). - - 2. **Review**: If the servers are able to verify active observers, the region is presented to MeshMapper administrators for review. Administrators will ensure the region isn't a duplicate, is named correctly, notes entered during onboarding are reviewed, etc. - - 3. **Activation**: Once reviewed, the region is approved and will become available for wardriving. It can take up to 5 minutes after deployment for the MeshMapper MQTT engine to start pulling in local data. +When your region is approved, you'll get an invite by email, or by Discord DM if you linked Discord. Sign in or create a MeshMapper account and accept it. That one account signs you in to both the [portal](portal.md) and your region's admin panel. -If you associated your Discord account during the onboarding process, you will receive automatic messages from MeshMapper with onboarding status. +!!! warning "Stay active" + Admins who don't sign in to the admin panel for more than 90 days may be marked inactive or have their access removed. Inactive admins aren't consulted on changes to their region, and new admins may be added if a region has no active admins. -While your request is pending, your region's subdomain (`https://.meshmapper.net`) shows a status page for the application, including whether MQTT observer verification has passed. You can also ask the Discord bot: `@MeshMapper !status `. +## After You Submit -> [!WARNING] -> Pending onboarding requests that have not passed MQTT verification in 3 days will automatically be deleted. + 1. **Observer check**: MeshMapper checks that an observer is reporting from your region's code. This takes up to 5 minutes once your observer is online. + 2. **Review**: The MeshMapper team reviews the request (name, boundary, conflicts with other regions, your notes). + 3. **Go live**: Once approved, your region is live. Repeaters and pings can take up to 5 minutes to appear on the map. -## Legacy Data +While your request is pending, `https://.meshmapper.net` shows its status, including whether an observer has been detected. You can also ask the Discord bot: `@MeshMapper !status `. If you linked Discord, you'll get DMs as your request moves along. -If you have historical coverage data from other systems, it can be imported into MeshMapper. This data will appear on a separate layer and is not included in leaderboard statistics. See [Data Upload](https://wiki.meshmapper.net/dataupload/) for format requirements. +!!! warning + Requests with no detected observer after 3 days are automatically deleted. You'll get reminders by email (and Discord, if linked) until then. diff --git a/docs/overrideduplicates.md b/docs/overrideduplicates.md index fca56b9..020e929 100644 --- a/docs/overrideduplicates.md +++ b/docs/overrideduplicates.md @@ -1,47 +1,49 @@ # Overriding Duplicate ID Detection -MeshMapper's default behavior is to aggressively quarantine repeaters and pings with colliding ID's to ensure map accuracy (see [Duplicate Repeater IDs](https://wiki.meshmapper.net/duplicaterepeaterid/)). However, some regions may prefer to visualize all repeaters and connections, even if the data attribution is technically ambiguous. +By default, MeshMapper won't link pings to repeaters it can't tell apart, and marks those repeaters **Ambiguous** (see [Duplicate Repeater IDs](duplicaterepeaterid.md)). Some regions would rather see every possible repeater and connection, even when it's not certain which one was involved. -The **Disable Duplicate ID Detection Logic** setting allows regions to bypass these safety checks. +The **Disable Duplicate ID Detection Logic** setting turns these checks off. !!! danger "Data Integrity Warning" - Enabling this setting compromises the accuracy of the map and data. - - Because the system cannot distinguish between two repeaters sharing the same ID (e.g., `A1`), coverage lines may be drawn to the wrong location, and "Max Range" statistics may be falsely inflated. + Turning this on makes the map less accurate. When two repeaters share an ID (e.g. `A1`), MeshMapper can't tell them apart, so lines may be drawn to the wrong repeater and **Max Range** may be inflated. + + As the admin panel warns: *"The MeshMapper administration team will not be available to assist with data validation or cleanup. Proceed at your own risk."* ## How to Enable -1. Region administrators can log in to the **Admin Portal**. -2. Navigate to the **Settings** tab. -3. Check the box for **Disable Duplicate ID Detection Logic**. -4. Click **Save Settings**. +1. Sign in to your region's admin panel. +2. Open **Settings → Repeaters, Neighbours & Scopes**. +3. Tick **Disable Duplicate ID Detection Logic**. +4. Save your settings. + +*For a region in a [multiregion group](multiregions.md), this is set by the group admin under **Group Defaults**.* + +## What Changes -*Note: If your region is part of a Multi-Region Group, this setting must be enabled by a Master or Global Administrator.* +### On the Map -## Changes to System Behavior + - **Repeaters**: no repeater is marked Ambiguous. Colliding repeaters show in their normal colours (green, pink or grey). + - **Ping lines**: lines are drawn from pings to **every** repeater matching an ambiguous hop. + - **Neighbour and backbone links**: drawn and counted for colliding repeaters too. + - **Public warning**: an orange **warning** button (**Data Accuracy Warning**) appears at the top right of the map, telling visitors the region has turned off duplicate detection. -When this mode is active, the system alters its logic in the following ways: +### When Data Comes In -### 1. Map Visualization -* **Icons:** Repeaters involved in a collision will no longer display the red **Excluded** icon. They will appear as standard Active repeaters (Orange/Grey/Green). -* **Coverage Lines:** The map will draw connection lines from pings to *all* repeaters that match the ID, even if the ping data is ambiguous. -* **Neighbor Lines:** Neighbor lines will be drawn for every repeater sharing a colliding ID. -* **Public Warning:** A warning icon will appear on the public map interface (below the Help button) to inform visitors that the region has opted out of standard validation logic. + - **No automatic Ambiguous status**: new adverts no longer trigger the check, so colliding repeaters, including new ones, stay as they are. + - **Pings**: a hop that matches more than one repeater is stored against all of them instead of being left unlinked. -### 2. Data Ingestion -* **Persistence:** The system will no longer automatically force existing repeaters into "Excluded" status when a collision is detected. If you manually set a duplicate repeater to **Active**, it will remain Active. -* **New Collisions:** To ensure admins are still aware of issues, *newly discovered* repeaters that cause a collision will still default to "Excluded" initially. However, unlike the standard mode, you can manually change them to "Active" without the system reverting your change on the next ping. Regardless of being "Excluded", the repeater will still function as being "Active". +### Leaderboards -### 3. Leaderboards -* **Local Leaderboard:** Duplicate repeaters will be included in the regional "Best Repeaters" and "Max Range" tables. -* **Global Leaderboard:** To protect the integrity of the global rankings, regions with this setting enabled are **excluded** from the Global Leaderboard. Your repeaters will not appear. + - **Region leaderboard**: colliding repeaters are included, and ambiguous pings count towards every matching repeater. + - **Global leaderboard**: the region's repeaters aren't included. Its wardrivers still count. ## Summary of Differences -| Feature | Standard Mode | Override Mode | +| Feature | Standard | Override | | :--- | :--- | :--- | -| **Duplicate Repeater Status** | Forced to "Excluded" (Red) | Can be manually set to "Active" | -| **Ambiguous Pings** | Ignored / Not drawn | Drawn to all matching candidates | -| **Neighbor Lines** | Drawn only for unique IDs | Drawn for all colliding IDs | -| **Max Range Stats** | Calculated only for verified unique IDs | Calculated for all IDs (may be inaccurate) | -| **Global Leaderboard** | Included | **Excluded** | \ No newline at end of file +| **Colliding repeaters** | Marked Ambiguous (red) automatically | Never marked Ambiguous | +| **Ambiguous pings** | Left unlinked; Duplicate lines only on a single selected ping | Linked and drawn to every matching repeater | +| **Neighbour and backbone links** | Only between repeaters that aren't Ambiguous | Include colliding repeaters | +| **Max Range** | Only from pings where the repeater's ID was clear | From every matching ping (may be inflated) | +| **Global leaderboard** | Repeaters included | Repeaters **not** included | +| **Public map** | No warning | **Data Accuracy Warning** shown | diff --git a/docs/portal.md b/docs/portal.md index 47be072..3331aa4 100644 --- a/docs/portal.md +++ b/docs/portal.md @@ -4,21 +4,46 @@ **Portal URL:** [https://portal.meshmapper.net](https://portal.meshmapper.net) -You can also reach it from any region map via the **About** menu → **My Portal / Sign in**. +You can also reach it from any region map via **About → My Portal / Sign in**. --- ## Creating an Account 1. Open the portal and choose **Register**. -2. Pick a username (3–30 characters; letters, numbers, `_`, `.`, `-`), enter your email address, and choose a password (8+ characters). -3. Check your inbox for a **verification email** and click the link. Verification links expire after 24 hours — you can request a new one from the login screen if needed. -4. Once verified, log in with your username (or email) and password. +2. Pick a username (3–30 characters; letters, numbers, `_`, `.`, `-`). Your username can't be changed later, and some names like `admin` or `meshmapper` are reserved. +3. Enter your email address and choose a password (at least 12 characters; common passwords, or ones containing your username, email or "MeshMapper", are rejected). +4. Check your inbox for a **verification email** and click the link. Verification links expire after 24 hours — you can request a new one from the login screen if needed. +5. Once verified, log in with your username (or email) and password. Forgot your password? Use the **password reset** option on the login screen — a reset link is emailed to you (valid for 1 hour). +### Sign in with Discord + +You can also use **Sign in with Discord** on the login screen: + +- If that Discord account is already linked, you're signed in. +- If its verified email matches an existing account, it links to that account automatically. +- Otherwise a new account is created, with no password. + +Under **Settings → Discord** you can **Connect Discord** or **Disconnect**, and turn on **Show my Discord avatar on leaderboards**. + +- A Discord-only account can **Set password** at any time. +- While Discord is connected, you can **Remove password (use Discord only)**. +- You must set a password before you can disconnect Discord. + !!! info "One account for the portal and admin panels" - A region administrator uses the same MeshMapper account for the portal and every [admin panel](admins.md) they can access. Accept an administrator invite or have access granted to your existing verified account. You do not need a separate admin login. + A region administrator uses the same MeshMapper account for the portal and every [admin panel](admins.md) they can access. You do not need a separate admin login. + +### Admin Invites + +If you're invited to be an administrator, you get an invite link. It lasts 7 days and is tied to one email address or Discord account. + +- New to MeshMapper? Choose **Create account & accept**. +- Already have an account? Choose **Sign in & accept**. +- Already signed in? Choose **Accept admin access**. + +Afterwards, **Go to the admin panel** takes you to [admin.meshmapper.net](https://admin.meshmapper.net). --- @@ -30,10 +55,12 @@ The in-browser signing is built on **Liam Cottle's [meshcore.js](https://github. **To link a device:** -1. Log in to the portal and choose to link a device. -2. Connect your MeshCore companion to the browser via **USB** or **Bluetooth** when prompted. -3. The portal sends a one-time challenge to your radio, which signs it and returns the signature. This happens automatically in a few seconds. -4. Optionally give the device a label (e.g., "Car T1000"). Done! +1. Log in to the portal and choose **Link a companion**. +2. Choose **Connect over Bluetooth**, or **USB instead**. If the companion is connected to your phone, close the MeshCore app on it first. +3. The portal sends a one-time challenge to your radio, which signs it and returns the signature. This happens automatically in a few seconds. The challenge expires after 2 minutes. +4. Done! The device shows up under **Your companions** using its own name. + +You can also sign in and link companions from the MeshMapper mobile app. The app shows up under **Settings → Connected apps**, where you can **Revoke** it. **Browser requirements:** @@ -58,13 +85,16 @@ Device linking uses the Web Serial / Web Bluetooth APIs, which are only availabl ## What You Can Do -Once logged in with at least one linked device: +The portal has these tabs: **Overview**, **Regions**, **Sessions**, **Companions**, **Repeaters** and **Profile Settings**. + +- **Overview**: your points, grid squares mapped, regions driven, companions and awards. +- **Regions**: the regions you've driven. **View on map** opens that region's map with only your pings. A "Showing all your pings" banner appears; click **Exit** to go back to the normal map. +- **Sessions**: your wardriving sessions across every region, 50 per page. You can search, filter by region, and sort by **Newest first**, **Oldest first** or **Most pings**. Use **View** to see a session on the map, or **Delete** to remove its pings. +- **Companions**: the devices linked to your account. +- **Repeaters** ("Repeaters you administer"): repeaters you've logged in to as admin from the app. Use **Edit** to set Hardware, Antenna, Transmit power, Height above ground, Power source (Mains, Solar, Battery or PoE) and a Site note (up to 200 characters). Use **Remove claim** to drop a repeater. +- **Profile Settings**: set your "Leaderboard display name — shown publicly and must be unique" (up to 60 characters, and it can't be "Anonymous"). You can also change your email (you'll need to verify the new one) or your password. -- **View your sessions** — Your wardriving sessions across every region, with ping counts. -- **View your pings on the map** — Jump from the portal straight to a region map showing only *your* contributions ("My Pings" mode). -- **Delete your data** — Remove the pings from a single session, or delete everything you've ever contributed. Deletions apply across all regions and take effect on the map immediately. -- **Set a display name** — Choose the name shown on your profile and leaderboards. -- **Manage your account** — Change your email address or password. +To delete everything, use **Danger zone → Delete ALL my pings**. It asks you to confirm twice. Deletions apply across all regions and the map updates immediately. !!! warning "Deletions are permanent" Deleting pings from the portal permanently removes them from MeshMapper's coverage data. There is no undo. @@ -73,6 +103,8 @@ Once logged in with at least one linked device: ## Privacy -The portal only ever shows you data belonging to devices you have cryptographically proven you own. Region administrators can still manage data within their own regions (see [Admin Portal](admins.md)), but your portal account and email address are never displayed publicly. +The portal only ever shows you data belonging to devices you have cryptographically proven you own. Region administrators can still manage data within their own regions (see [Admin Portal](admins.md)). + +Your display name is public; your username and email are not. To hide your name on the map and leaderboards, turn on [Anonymous Mode](app_connection_guide.md#anonymous-mode) in the app. For questions or problems with the portal, ask in the [MeshMapper Discord](https://discord.gg/tyXbecdxgr). diff --git a/docs/privacy.md b/docs/privacy.md index d28ccc6..e5b82eb 100644 --- a/docs/privacy.md +++ b/docs/privacy.md @@ -1,6 +1,6 @@ # Privacy Notice -**Last Updated:** July 1, 2026 +**Last Updated:** September 28, 2026 MeshMapper ("we", "us", or "our") operates the MeshMapper platform at meshmapper.net and its associated regional subdomains. This Privacy Notice explains how we collect, use, and protect your information when you use our services. @@ -9,12 +9,14 @@ MeshMapper ("we", "us", or "our") operates the MeshMapper platform at meshmapper ### Account Information When you sign in or link your account via Discord OAuth, what we receive depends on where you authenticate: -- **My MeshMapper portal:** with your permission, we receive your Discord user ID, username, avatar, and the email address associated with your Discord account. Your avatar is stored only for optional display on your public leaderboard profile, and only if you choose to enable it. +- **My MeshMapper portal:** with your permission, we receive your Discord user ID, username, avatar, and the email address associated with your Discord account. Your Discord avatar reference is stored with your account, but it is only shown on your public leaderboard profile if you turn that option on. - **Region administration and the main site:** we receive only your Discord user ID and username. We use your Discord user ID to send you automated notifications, such as direct messages about your regions or pending repeaters. -If you create a **My MeshMapper** portal account, we store your chosen username, your email address (used for account verification and password resets), and a hash of your password. Your email address is never displayed publicly and is not used for marketing. +If you create a **My MeshMapper** portal account, we store your chosen username, your display name, your email address (used for account verification and password resets), a hash of your password, and when the account was created and last signed in. Your email address is never displayed publicly and is not used for marketing. + +If you contact us through the region onboarding form or the contact form on the website, we receive the email address and message you provide. ### Location and Coverage Data When you participate in wardriving sessions, the following data is collected: @@ -24,18 +26,21 @@ When you participate in wardriving sessions, the following data is collected: - **Session metadata** including timestamps, region, and session identifiers - **Node identifiers** for mesh network repeaters and devices encountered, including your device name - **Device identity**, including your device's public key — a persistent, unique identifier for your mesh node -- **Device and radio details**, such as your radio model, app version, radio frequency, transmit power, GPS accuracy, and noise-floor readings +- **Device and radio details**, such as your radio model, app version, radio frequency, transmit power, external-antenna setting, GPS accuracy, altitude, and noise-floor readings This data is essential to the core function of MeshMapper: building community-driven RF coverage maps. +MeshMapper also records publicly broadcast mesh adverts (node name, public key, and time last heard) received by observers, including from people who do not use MeshMapper. + Note that by default the wardriving app does **not** broadcast your GPS coordinates over the mesh radio channel — pings carry a short anonymous token on the air, and your coordinates are transmitted only to our servers over the internet. An opt-in setting ("Broadcast My Coordinates") is available for users who want their position visible on the air. ### Technical Data We may collect standard technical information such as: -- IP addresses (used for rate limiting and abuse prevention; full IP addresses are also recorded in server access logs, which are retained for approximately 30 days) -- Browser user-agent strings -- Server access logs +- IP addresses and browser user-agents, used for rate limiting and abuse prevention. Full IP addresses are recorded in server access logs kept for about 30 days. For signed-in app sessions, we also store the IP address and user-agent last used with each app login token until that token expires (at most one year). +- Privacy-first, cookieless website statistics run on our own servers. Your country is looked up from your IP address using a local database, and the IP address is not stored for statistics. +- If you ask the MeshMapper Discord bot a question, your Discord username, the channel, your question and the bot's answer are logged (the most recent 1,000 interactions). +- If you submit feedback or a bug report from the app, it includes your device's public key, app version and platform, and any debug logs you choose to attach (which include your phone's OS version and model). ## How We Use Your Information @@ -57,6 +62,8 @@ We use the information we collect to: ## Data Storage and Security +- The wardriving app uses your location in the background during an active wardriving session, and Bluetooth, Wi-Fi or USB to reach your radio. + - All data is stored in databases on our servers. - Sessions are managed server-side using PHP sessions and API key authentication. - Data sent from the wardriving app to our servers is transmitted over secure (HTTPS/TLS) connections, and our MQTT data ingestion also runs over TLS. @@ -76,17 +83,20 @@ MeshMapper integrates with the following third-party services: - **AWS Open Data Terrain Tiles** for 3D terrain elevation data - **Nominatim** for geocoding / location search ([Nominatim Usage Policy](https://operations.osmfoundation.org/policies/nominatim/)) - **OpenStreetMap** for map data ([OpenStreetMap Privacy Policy](https://wiki.osmfoundation.org/wiki/Privacy_Policy)) -- **LetsMesh.net** as the MQTT broker for wardriving data ingestion ([LetsMesh](https://letsmesh.net/)) +- **MeshMapper MQTT broker** — observer data is ingested through MeshMapper's own MQTT broker over TLS. We also collect observer data published to the public LetsMesh.net broker, which is not MeshMapper infrastructure and is run under its operator's own terms ([LetsMesh](https://letsmesh.net/)) +- **Discord CDN** for loading public leaderboard avatars +- **Email delivery** — account, invite and notification emails are sent through an email relay service - **GitHub** for handling in-app bug reports, which may include information you choose to submit in a report ([GitHub Privacy Statement](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement)) - **OpenTopoData** for elevation lookups ([OpenTopoData](https://www.opentopodata.org/)) - **Content delivery networks** — our web interface loads fonts, scripts, and an anti-abuse CAPTCHA widget from third-party CDNs (including Google Fonts, unpkg, jsDelivr, Cloudflare cdnjs, and cap.js). These providers may receive your IP address and browser user-agent when their assets are loaded. ## Data Retention -- Coverage and session data is retained indefinitely to maintain historical map accuracy. -- Records of individual mesh repeaters that have not been heard for 30 days may be automatically removed. -- You can view and delete your own contributed data yourself through the [My MeshMapper portal](portal.md) after verifying ownership of your device. -- You may also request deletion of your data by contacting us at admin@meshmapper.net. +- Coverage and session data is retained indefinitely to maintain historical map accuracy. Regions may remove pings whose repeaters have moved or disappeared. +- Repeaters not heard for 30 days are marked inactive. Records of other mesh devices heard on the air are removed after about 30 days, and some repeater metadata expires after 90–180 days. +- You can view your sessions and delete some or all of your contributed pings (and the leaderboard credit from them) through the [My MeshMapper portal](portal.md) after verifying ownership of your device. +- Deleted data may remain in routine database backups until those backups are overwritten. +- To delete your account or remaining session records, contact us at admin@meshmapper.net. ## Your Rights diff --git a/docs/region_boundaries.md b/docs/region_boundaries.md index b7a5040..15932ff 100644 --- a/docs/region_boundaries.md +++ b/docs/region_boundaries.md @@ -1,82 +1,54 @@ # Defining a Region's Boundary -MeshMapper allows for different methods of defining a region's boundary using the web utilities in the region admin panel: defined radius around a point (default), manually defined polygon from user-input points, and imported geoJSON formatted text blocks. +Every region needs a boundary. It decides where wardriving counts for the region, and what's drawn as the region's border on the map. -All of the following methods are accessed via the admin panel for each region, under the `Settings` menu. Scroll to near the bottom of the page to reach the `Region Boundary` interface. +The easiest way is **Load Boundary**, which builds the boundary from real state/province, county or local borders from OpenStreetMap. You can also draw one by hand. The region's radius is worked out from the boundary automatically. -If a boundary change removed part of your area, open that editor and correct the polygon or re-import a saved GeoJSON file. The history records that a boundary changed, but it is not an undo button and does not keep a downloadable copy of the old shape. Ask a global administrator for help if you no longer have the original boundary. +!!! tip "Coordinate with your neighbours" + Regions can't overlap, so coordinate with neighbouring region administrators. Following the same borders (e.g. county lines) lets wardrivers cross from one region to the next without interruption. -Use **Export GeoJSON** in the boundary editor to download the current shape. Save a copy before a large edit. +## Opening the Editor -Coordinate boundaries with neighboring region administrators. The onboarding form checks for substantial overlap, and the MeshMapper team reviews new requests before approval. +Open your region's admin panel, go to **Settings**, and expand **Region Boundary** (the last section). Click **Save All Settings** when you're done. You can't save while a boundary edit is still open; click **Done** on the map first. -## Radius Around a Point +Before a big change, click **Export GeoJSON** to download the current boundary. The history records that the boundary changed, but it doesn't keep a copy of the old shape. If you lose a boundary, ask a global administrator for help. -*Note: This method works best for isolated regions with no nearby neighbors, as adjacent neighboring regions will result in overlap or coverage gaps, resulting in potentially incorrect data inside overlaps or preventing seamless region transition for wardrivers crossing gaps.* +## Load Boundary (Recommended) -The default method of defining a region's boundary is by using a defined radius around a center point. For this method, the admin drops/moves a marker pin onto the map at the center of the desired region, then sets a radius distance around that point. The region boundaries will be circular, with no consideration given to political or geographical boundaries. + 1. Check the **Country** code (two letters) above the map. + 2. **Drag the pin** to the middle of your region. The borders around it load automatically, or click **Load Boundary** (shown on the map as **Auto Boundary** in the admin panel). + 3. Choose a level: **State/Prov**, **County** (default) or **Local** (municipality, where available; otherwise County is used). + 4. **Click the green areas** you want, or Ctrl/Shift-drag a box around several. Use the arrows around the pin to load more areas. + 5. Click **Use selected** to merge them into one boundary. -In the image below, the radius-based boundary line is shown as a red dashed line. Its center point is shown both as a dropped pin on the map and as GPS coordinates just above the top left corner of the map. The radius distance (in km) is input next to the GPS coordinates. This boundary type is overridden - but still displayed to admins - if any polygon-based boundary is used. +On the map, **purple** is existing regions, **green** is areas you can pick, and **blue** is your selection. Areas that belong to another region can't be picked. -![Editor Interface with Radius Boundary Shown as Red Dashed Line](./assets/region-boundaries-editor-interface.png "Editor Interface with Radius Boundary Shown as Red Dashed Line") +The **OSM | GB** switch picks the source: OpenStreetMap (default) or geoBoundaries (cut at the shoreline). -## Manually Defined Polygon Boundary +### Coastlines and Islands -This type of boundary is created using the map interface and mouse, and works best for regions with simple boundaries. Use the `Draw a Polygon` button (the filled pentagon just below the zoom buttons) to start the process. At each desired vertice of the polygon, single click the left mouse button to add a point. Proceed methodically around the desired edges (we recommend going either clockwise or counterclockwise consistently around the edge, and once finished then return to make any adjustments or corrections). This continues until the last vertice is placed, then mouse over to the original starting vertice and double click it to complete the polygon. To cancel a drawing in progress, press the Escape key on your keyboard. + - **Fill water between** (under **Advanced**): when merging, fills water between islands and the mainland. + - **Extend over water**: sketch an area over water and add it to the boundary. -![Editor Interface with Draw Polygon Button Shown](./assets/region-boundaries-draw-polygon.png "Editor Interface with Draw Polygon Button Shown") +## Drawing or Editing by Hand -To edit an existing polygon, use the `Edit Layers` button, located just above the trashcan on the left side of the map. Pressing this will display all of the vertice points in the existing polygon and allow you to: click and drag them to new positions, delete them by single clicking a shaded square, and add new vertices by single clicking the hollow squares that appear halfway between existing vertices. When finished, be sure to click the `Save` button next that appeared next to the `Edit Layers` button when you activated edit mode. + - **Draw**: under **Advanced Mapping**, click **Draw Boundary**. Click the map to add points, then press Enter or click **Finish**. Press Esc to cancel. + - **Edit**: click **Edit** on the map. Drag points to move them. Click a grey dot or double-click an edge to add a point. Press Delete or right-click to remove one (or use **Delete point(s)**). Click **Done**, then **Save All Settings**. + - **Clear**: click **Clear** to remove the boundary and start again. -![Editor Interface with Edit Layers Mode Displayed](./assets/region-boundaries-edit-polygon.png "Editor Interface with Edit Layers Button Shown") +## Custom GeoJSON (Special Circumstances Only) -## geoJSON Polygon Boundary +Custom GeoJSON boundaries are only accepted in special circumstances. Use **Load Boundary** unless the MeshMapper team has asked you to import a file. -Using a geoJSON file is the recommended method for regions with complex borders and/or adjacent neighbors (with coordination). +To import one, click **Import GeoJSON** under **Advanced Mapping**, then upload the file or paste its contents and click **Import**. -### Importance of Inter-Region Coordination + - Accepted: `Polygon`, `MultiPolygon`, `Feature` and `FeatureCollection`. + - The largest area becomes the boundary; others appear as dashed outlines you can click to use instead. + - Only one outline is saved, and holes are ignored. + - Files aren't simplified, so very detailed files may slow your browser. -This method of creating a region boundary involves assembling a geoJSON file with a single polygon shape, then copying the text inside the file and pasting it into the admin interface. The primary benefits of using this method are to reduce inter-region overlap, to provide consistency with region borders when wardriving, and to easily incorporate planned future mesh expansion in defined political or geographical boundaries. Several regions have seen success with geoJSON boundaries using political boundaries as the defining lines - e.g. county/parish boundaries in the U.S. If wardriving users know that region boundaries follow a given political boundary or highway, the experience when wardriving is made easier to plan routes or to know when to activate wardriving in the MeshMapper app. With coordinated boundaries between regions, users can seamlessly transition between them without manual intervention in the app. +## Example: Coordinated Regions -It is **strongly** recommended to coordinate with neighboring region administrators when planning region boundaries. The image below shows a series of regions between roughly Houston, Texas, and Pensacola, Florida where the regional admins have successfully coordinated boundaries. Wardrivers could start to the west of Houston and drive east past Pensacola without interruption in data collecting if so desired. +The regions between roughly Houston, Texas and Pensacola, Florida share county-based borders, so a wardriver can drive from west of Houston to past Pensacola without interruption. -![Multiple Regions Have Coordinated Boundaries using geoJSON Files](./assets/region-boundaries-coordination.png "Multiple Regions Have Coordinated Boundaries using geoJSON Files") - -### Constructing the geoJSON File - -Once a method of defining a region's boundaries has been chosen, the next step is to find a GIS data source from which to construct the geoJSON file. - -*Note: MeshMapper expects a single contiguous polygon. Areas with islands or other disjointed boundaries may require manual editing before importing. Double check your data source to see if this applies to you.* - -Some available resources for GIS data based on political boundaries include: -* [Vercel Boundary Maker (US Counties - Creates ready-to-import geoJSON files](https://nc-boundary-maker.vercel.app/) -* [Canadian Provincial Boundaries](https://open.canada.ca/data/en/dataset/85efc01b-163f-ebba-2378-c43eadfb3b3f/resource/4137a99d-f5dd-4e69-9e13-a587ff6eaa55) -* [Canadian Census Boundaries](https://www12.statcan.gc.ca/census-recensement/2021/geo/sip-pis/boundary-limites/index-eng.cfm) -* [United Kingdom Local Authority Districts](https://geoportal.statistics.gov.uk/datasets/ons::local-authority-districts-may-2025-boundaries-uk-bfc-v2/about) -* [Australian Administrative Boundaries](https://data.gov.au/data/dataset/geoscape-administrative-boundaries) -* [New Zealand Geographic Data Service](https://datafinder.stats.govt.nz/) - - If your data set is not ready to import into MeshMapper (already formatted as a single contiguous polygon including the intended area for your region), you will likely need GIS software to make the necessary edits and export to geoJSON format. One commercial product is [ArcGIS Pro](https://www.esri.com/en-us/arcgis/products/arcgis-pro/overview). A free, open source alternative is [QGIS](https://qgis.org/) - - While it is beyond the scope of this document to outline every possible necessary step to prepare a dataset for import into MeshMapper, the general process is as follows: -1. Import your data into your GIS software suite of choice -2. Merge multi-polygons into a single polygon layer -3. Dissolve the single polygon layer to remove internal borders and any remaining data from previous multi-polygons -4. Clean your polygon shape for importing into MeshMapper (remove areas that aren't contiguous) if necessary -5. Export your cleaned layer to geoJSON, copy the contents of that file, paste into the MeshMapper admin panel - -Using the [Houston region](https://hou.meshmapper.net) as an example, the process is illustrated in the images below: - -* Importing data: -![Houston Region County Data, Imported into QGIS](./assets/region-boundaries-hou1.png "Houston Region County Data, Imported into QGIS") - -* Merging data: -![Houston Region County Data, Merged Into a Single Polygon](./assets/region-boundaries-hou2.png "Houston Region County Data, Merged Into a Single Polygon") - -* Dissolving data: -![Houston Region Data, Dissolved](./assets/region-boundaries-hou3.png "Houston Region Data, Dissolved") - -* Cleaning data (deleting islands & other disconnected areas): -![Houston Region Data, Editing View](./assets/region-boundaries-hou4.png "Houston Region Data, Editing View") - -Again, it is beyond the scope of this document to attempt to explain or troubleshoot all possible situations when dealing with GIS data. There are many, many tutorials and troubleshooting tips available with a web search. The goal is to produce a single *contiguous* polygon shape in geoJSON format and then import that data into MeshMapper via copy/paste. +![Multiple regions with coordinated boundaries](./assets/region-boundaries-coordination.png "Multiple regions with coordinated boundaries") diff --git a/docs/release-notes/260212.md b/docs/release-notes/260212.md index f831efc..6f5897f 100644 --- a/docs/release-notes/260212.md +++ b/docs/release-notes/260212.md @@ -6,7 +6,7 @@ * **Discord Integration** — Region administrators can now link their Discord! This will allow administrators to receive notifications about their region from the MeshMapper bot (for example, when a new repeater has sent an advert and its ID is now in collision). Find this setting in the "User Settings" tab of the admin panel. * **Administration Popup** — A new "Administration" option on the map displays the region's administrators and contact information, making it easier for visitors to reach out to local maintainers. Visitors can send messages to the administrators through the Discord integration/MeshMapper bot here, if there is at least one region administrator with their Discord linked and that notification type is enabled. * **Region Message** — Administrators can now set a custom message (e.g., local Discord server invite, website link) that appears to visitors in the Administration popup. This allows administrators to direct map visitors to local resources. -* **Disable Duplicate ID Detection** — Added the ability for region admins to opt-out of strict duplicate ID detection. This allows regions to visualize all data even if repeater IDs collide. [Read about this in more detail here.](https://wiki.meshmapper.net/overrideduplicates/) +* **Disable Duplicate ID Detection** — Added the ability for region admins to opt-out of strict duplicate ID detection. This allows regions to visualize all data even if repeater IDs collide. [Read about this in more detail here.](../overrideduplicates.md) * **Onboarding Status** — New regions pending onboarding will display in the Maps dropdown with a landing page indicating that onboarding is pending. Optionally linking ones Discord with the onboarding form allows for automated status updates sent directly from the MeshMapper bot. * **Users** — Region administrators now have the ability to create Users. Creating a User allows you the ability to combine multiple companions under a single "primary" companion, which will aggregate a users statistics and contributions under that single companion on the leaderboard. This is also the first stepping stone into a planned portal that will allow end-users the ability to manage their own contributions, see their own detailed statistics, etc. diff --git a/docs/release-notes/260219.md b/docs/release-notes/260219.md index eee185a..b2e7510 100644 --- a/docs/release-notes/260219.md +++ b/docs/release-notes/260219.md @@ -2,21 +2,21 @@ ### ✨ New Features -* **Notes for Repeaters and Companions** — Added ability to add notes to repeaters and companions in the admin panels. (Thanks Noodles) [See More](https://wiki.meshmapper.net/admins/#data-management) +* **Notes for Repeaters and Companions** — Added ability to add notes to repeaters and companions in the admin panels. (Thanks Noodles) [See More](../admins.md#data-management) ![Image](https://meshmapper.net/img/upload_20260219_092727_008ad65a.jpg) -* **Lock Repeater GPS** — Added option in admin panels to lock repeater GPS coordinates to prevent adverts from updating the location. (Thanks jstockton) [See More](https://wiki.meshmapper.net/admins/#repeaters) +* **Lock Repeater GPS** — Added option in admin panels to lock repeater GPS coordinates to prevent adverts from updating the location. (Thanks jstockton) [See More](../admins.md#repeaters) ![Image](https://meshmapper.net/img/upload_20260219_092831_4a3de45d.jpg) -* **Social Media Links** — Administrators can now add social media links to the "Region Info" page of their regions map. (Thanks bbrodka) [See More](https://wiki.meshmapper.net/admins/#system-settings) +* **Social Media Links** — Administrators can now add social media links to the "Region Info" page of their regions map. (Thanks bbrodka) [See More](../admins.md#system-settings) ![Image](https://meshmapper.net/img/upload_20260219_092913_550d6acb.jpg) ![Image](https://meshmapper.net/img/upload_20260219_092605_43961f64.jpg) -* **Offline Observer Notifications** — Administrators can now opt-in to Discord notifications when an observer hasn't sent data to MeshMapper within the Stale Repeater Age time set on the admin page. (Thanks mrzarquon) [Read more about it here](https://wiki.meshmapper.net/admins/#notifications) +* **Offline Observer Notifications** — Administrators can now opt-in to Discord notifications when an observer hasn't sent data to MeshMapper within the Stale Repeater Age time set on the admin page. (Thanks mrzarquon) [Read more about it here](../admins.md#notifications) ![Image](https://meshmapper.net/img/upload_20260219_092952_0384e389.jpg) diff --git a/docs/release-notes/260227.md b/docs/release-notes/260227.md index c054151..eea829d 100644 --- a/docs/release-notes/260227.md +++ b/docs/release-notes/260227.md @@ -6,13 +6,13 @@ ![Image](https://meshmapper.net/img/upload_20260227_213104_f11b4c73.jpg) -* **Profiles & Awards** — Companion/user profiles and an awards system have been added to MeshMapper! View any profile by clicking a name on a leaderboard or using the "Profiles" search button. Awards are granted automatically for milestones (data points, grid squares, leaderboard rank) or manually by administrators. See the full details and what awards are available to be earned on the [Profiles & Awards](https://wiki.meshmapper.net/awards/) wiki page. +* **Profiles & Awards** — Companion/user profiles and an awards system have been added to MeshMapper! View any profile by clicking a name on a leaderboard or using the "Profiles" search button. Awards are granted automatically for milestones (data points, grid squares, leaderboard rank) or manually by administrators. See the full details and what awards are available to be earned on the [Profiles & Awards](../awards.md) wiki page. ![Image](https://meshmapper.net/img/upload_20260227_213703_e8faf1bf.jpg) -* **Pending Repeater Approval** — Regional administrators can now enable a flag that has new repeaters enter in a "Pending" state, needing approval by a regional administrator before appearing on the map. Pending repeaters have 3x the regions Stale Repeater Timer before being automatically activated, or are deleted if no advert is received within 1x the regions Stale Repeater Timer. A new Discord notification type has been created that will notify regional administrators once a day if the region has any pending repeaters. This is an anti-abuse measure and should be used with caution, as it can cause inaccurate map data. [Read about it more here.](https://wiki.meshmapper.net/admins/#system-settings) +* **Pending Repeater Approval** — Regional administrators can now enable a flag that has new repeaters enter in a "Pending" state, needing approval by a regional administrator before appearing on the map. Pending repeaters have 3x the regions Stale Repeater Timer before being automatically activated, or are deleted if no advert is received within 1x the regions Stale Repeater Timer. A new Discord notification type has been created that will notify regional administrators once a day if the region has any pending repeaters. This is an anti-abuse measure and should be used with caution, as it can cause inaccurate map data. [Read about it more here.](../admins.md#system-settings) -* **New Administrators** — Regional administrators can now create new regional administrator accounts. Create the account and send the new administrator the registration link to complete their registration. [Read about it more here.](https://wiki.meshmapper.net/admins/#adding-a-new-administrator) +* **New Administrators** — Regional administrators can now create new regional administrator accounts. Create the account and send the new administrator the registration link to complete their registration. [Read about it more here.](../admins.md#adding-a-new-administrator) * **Top Explorers (Regional)** — The Top Explorers leaderboard, which awards a point for being the first to wardrive a grid square, has been added to regional leaderboards. (Thanks ded) diff --git a/docs/release-notes/260304.md b/docs/release-notes/260304.md index 5ee5743..c25b6b8 100644 --- a/docs/release-notes/260304.md +++ b/docs/release-notes/260304.md @@ -2,11 +2,11 @@ ### ✨ New Features -* **Effective Coverage Map** — A new map layer that visualizes coverage based on effective reach! [Read the details here](https://wiki.meshmapper.net/layers/) *(Thanks HerculesMulligan)* +* **Effective Coverage Map** — A new map layer that visualizes coverage based on effective reach! [Read the details here](../layers.md) *(Thanks HerculesMulligan)* ![Image](https://meshmapper.net/img/upload_20260304_174704_3564bc42.jpg) -* **Signal Strength Map** — A new map layer that color-codes coverage by signal strength (SNR), making it easy to identify strong and weak zones at a glance. [Read the details here](https://wiki.meshmapper.net/layers/) *(Thanks davidjay)* +* **Signal Strength Map** — A new map layer that color-codes coverage by signal strength (SNR), making it easy to identify strong and weak zones at a glance. [Read the details here](../layers.md) *(Thanks davidjay)* ![Image](https://meshmapper.net/img/upload_20260304_175903_005745e0.jpg) diff --git a/docs/release-notes/260320.md b/docs/release-notes/260320.md index 9906521..c1f276c 100644 --- a/docs/release-notes/260320.md +++ b/docs/release-notes/260320.md @@ -4,7 +4,7 @@ ### ✨ New Features -* **In-House MQTT Server** — The MeshMapper MQTT server is live! While MeshMapper can still use the letsmesh MQTT servers, having an in-house MQTT server provides a failsafe in case letsmesh goes down, or regions don't wish to use letsmesh. Information on the MQTT server [can be found on the wiki.](https://wiki.meshmapper.net/mqtt-main/). +* **In-House MQTT Server** — The MeshMapper MQTT server is live! While MeshMapper can still use the letsmesh MQTT servers, having an in-house MQTT server provides a failsafe in case letsmesh goes down, or regions don't wish to use letsmesh. Information on the MQTT server [can be found on the wiki.](../mqtt-main.md). * **Observers Admin** — Region administrators now have visibility into the observers feeding data into their region. Admins can see contribution counts as well as mute notifications (for when a companion has stopped reporting). @@ -22,9 +22,9 @@ ![Image](https://meshmapper.net/img/upload_20260320_093714_54c324d1.jpg) -* **Map Embedding** — Lightweight region maps can now be embedded externally. Various configuration parameters are available to fine-tune display. [See the wiki article for details](https://wiki.meshmapper.net/embedding/). +* **Map Embedding** — Lightweight region maps can now be embedded externally. Various configuration parameters are available to fine-tune display. [See the wiki article for details](../embedding.md). -* **Repeater List Embedding** — The grid view of 1-byte repeater ID's in current use is now available to be embedded. [See the wiki article for details](https://wiki.meshmapper.net/embedding/#repeater-id-grid). +* **Repeater List Embedding** — The grid view of 1-byte repeater ID's in current use is now available to be embedded. [See the wiki article for details](../embedding.md#repeater-id-grid). * **GeoJSON Import** — Regions now have the ability to define their boundries via GeoJSON import from the admin panel, or during onboarding. (Thanks @davidjay @clauwn) @@ -38,7 +38,7 @@ ![Image](https://meshmapper.net/img/upload_20260320_095023_3a982e29.jpg) -* **API Access** — MeshMapper now offers a Coverage API to allow regions to display coverage data on top of their existing tools. Information on response format and how to obtain an API key is [available on the wiki.](https://wiki.meshmapper.net/coverage-api/) +* **API Access** — MeshMapper now offers a Coverage API to allow regions to display coverage data on top of their existing tools. Information on response format and how to obtain an API key is [available on the wiki.](../coverage-api.md) * **Map Search** — As MeshMapper continues to expand, it's becoming more tedious to scroll the list of maps. A search bar has been added. diff --git a/docs/release-notes/260409.md b/docs/release-notes/260409.md index ba7f874..9fb5232 100644 --- a/docs/release-notes/260409.md +++ b/docs/release-notes/260409.md @@ -20,7 +20,7 @@ ![Image](https://meshmapper.net/img/upload_20260409_132008_68a0fd90.jpg) -* **Noise Floor Layer** — Replaced the noise heatmap with a new grid-based noise coverage layer. The previous heatmap interpolated noise floor values between data points, which created misleading smooth gradients in areas with no actual data — giving the false impression of known noise levels where none had been measured. The new layer displays noise floor readings per grid square, only where data actually exists, providing a more honest and accurate representation of RF conditions. The same calibration logic still applies. [See here for more details](https://wiki.meshmapper.net/layers/#noise-floor) +* **Noise Floor Layer** — Replaced the noise heatmap with a new grid-based noise coverage layer. The previous heatmap interpolated noise floor values between data points, which created misleading smooth gradients in areas with no actual data — giving the false impression of known noise levels where none had been measured. The new layer displays noise floor readings per grid square, only where data actually exists, providing a more honest and accurate representation of RF conditions. The same calibration logic still applies. [See here for more details](../layers.md#noise-floor) ![Image](https://meshmapper.net/img/upload_20260409_132109_cf03dc45.jpg) @@ -38,7 +38,7 @@ ![Image](https://meshmapper.net/img/upload_20260409_132330_9b00b0bf.jpg) -* **Custom Webhook Notification URL** — Administrators can now define a custom webhook URL at the region level to receive alert notifications (duplicate repeaters, pending repeaters, offline observers) on any HTTPS endpoint such as Home Assistant, custom tools, etc. *(Thanks Zeva)* [Read more about it here.](https://wiki.meshmapper.net/webhooks/) +* **Custom Webhook Notification URL** — Administrators can now define a custom webhook URL at the region level to receive alert notifications (duplicate repeaters, pending repeaters, offline observers) on any HTTPS endpoint such as Home Assistant, custom tools, etc. *(Thanks Zeva)* [Read more about it here.](../webhooks.md) ![Image](https://meshmapper.net/img/upload_20260409_132405_c0bf05e9.jpg) diff --git a/docs/reportbugs.md b/docs/reportbugs.md index f657086..8e8f2fc 100755 --- a/docs/reportbugs.md +++ b/docs/reportbugs.md @@ -2,12 +2,17 @@ MeshMapper is actively being developed using community feedback, and bugs are expected. -You can submit a ticket easily using our guided form: +You can submit a ticket using the guided form (also available from **About → Report Issue** on any map, and from the mobile app): Submit Bug or Feature Request -Alternatively, you can report bugs directly on the MeshMapper Central Issue Tracking and Project Planning Github repo here: +In the MeshMapper Discord, you can also tag the bot with **`!bug`** or **`!feature`** followed by a description. See [Bot Commands](botcommands.md). + +Alternatively, you can report bugs directly on the MeshMapper issue tracker on GitHub: -We also welcome ideas and suggestions to improve MeshMapper. MeshMapper is a community-driven product and all feedback is welcome. \ No newline at end of file +We also welcome ideas and suggestions to improve MeshMapper. It's a community-driven project and all feedback is welcome. + +!!! note + Due to the size and activity of the community, these are the **only** ways to submit tickets. The developers may miss requests sent any other way. diff --git a/docs/scopes-api.md b/docs/scopes-api.md index 6fd31cb..49387ca 100644 --- a/docs/scopes-api.md +++ b/docs/scopes-api.md @@ -7,7 +7,7 @@ GET https://yow.meshmapper.net/get_scopes.php ``` - On a **region** site: that region's own repeaters. -- On a **group** site (e.g. `pnw.meshmapper.net`): every enabled member region's repeaters, combined. +- On a **group** site (e.g. `pnw.meshmapper.net`): every enabled member region's repeaters, combined. A repeater carried by several members is counted once. There are no parameters. @@ -40,7 +40,7 @@ There are no parameters. | `zones` | The region codes counted in this answer: one code on a region site, every enabled member on a group site. | | `repeaters` | How many of this page's repeaters are enabled and public. This is the same population the map's Scope Finder tool checks, **not** the population MeshMapper's Scope Onboarding leaderboard uses: that board only counts repeaters inside the region's own drawn boundary, so a region with repeaters placed outside its boundary can show a different total there. | | `scoped` | How many of those repeaters carry at least one Mesh Scope, by any evidence, or put a scope on their own adverts (even one MeshMapper can't name yet). A repeater whose only answer is `✱ Not set` doesn't count. | -| `scopes` | One entry per scope name seen on this page, plus every name on the region's Scopes to Monitor list or set as its Wardriving Scope, even at zero repeaters. Sorted by `repeaters` highest first, then by name. | +| `scopes` | One entry per scope name seen on this page's repeaters, plus every name on the region's monitored list (see `monitored` below) or set as its Wardriving Scope, even at zero repeaters. Sorted by `repeaters` highest first, then by name. | ### Scope entry fields @@ -49,14 +49,16 @@ There are no parameters. | `name` | The scope name, as configured on the repeaters that carry it. | | `repeaters` | How many of this page's repeaters carry this scope. | | `default` | Of those, how many put this scope on their own adverts (as opposed to only being reported or observed carrying it). | -| `monitored` | `true` when this name is on the region's Scopes to Monitor list right now. | -| `wardriving` | `true` when this is the region's configured Wardriving Scope, the name it asks wardrivers' apps to use. | +| `monitored` | `true` when MeshMapper is watching for this name right now: the region's Scopes to Monitor list, which automatically includes its Wardriving Scope and scopes its repeaters have reported (up to 48 names). | +| `wardriving` | `true` when this is a configured Wardriving Scope of this region (on a group site, of any member), the name it asks wardrivers' apps to use. | Names and counts only. There is no per-repeater list, no repeater ID, and no key of any kind in this response. ## Caching -Sends `Cache-Control: public, max-age=300` and a strong `ETag`. Send the `ETag` back in `If-None-Match` to get `304 Not Modified` with no body when nothing changed. `generated_at` isn't part of the `ETag`. +Sends `Cache-Control: public, max-age=300` and a strong `ETag`. Send the `ETag` back in `If-None-Match` to get `304 Not Modified` with no body when nothing changed. `generated_at` isn't part of the `ETag`. A `304` still counts against the rate limit. + +Responses are gzip-compressed. ## Errors diff --git a/docs/systemstatus.md b/docs/systemstatus.md index a613fdd..d130223 100644 --- a/docs/systemstatus.md +++ b/docs/systemstatus.md @@ -1,12 +1,9 @@ # System Status -!!! note - The live status dashboard that used to be embedded on this page has been retired. - ## Checking MeshMapper Status - **Discord** — Outages and scheduled maintenance are announced in the [MeshMapper Discord server](https://discord.gg/tyXbecdxgr). This is the fastest place to check whether an issue is already known. -- **Maintenance mode** — When MeshMapper is undergoing maintenance, the wardriving app displays a maintenance message with details. You can continue wardriving in [Offline Mode](app_connection_guide.md#offline-mode) and upload your sessions once service is restored. -- **Your region's ingestion** — If the platform is up but your region's data seems stale, check **Region Info → Observers** on your region's map to see whether your region's MQTT observers are online, or ask the Discord bot: `@MeshMapper !status YOW`. +- **Maintenance mode** — During maintenance the map shows an **Under Maintenance** page (a warning banner may appear on the map beforehand), and the wardriving app shows a maintenance message. You can keep wardriving in [Offline Mode](app_connection_guide.md#offline-mode) and upload your sessions once service is restored. Individual regions can also pause wardriving, in which case the app shows the region's message. +- **Your region's ingestion** — If the platform is up but your region's data seems stale, open **Region → Observers** on your region's map to see whether its MQTT observers are online. The Discord bot's `!status YOW` shows the region's status and its data, repeater and observer counts (not whether observers are online right now). If you're seeing a problem that isn't announced anywhere, please report it — see [Report Bugs & Features](reportbugs.md). diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 5d89e86..e9bde1a 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -11,20 +11,20 @@ If you're having trouble with MeshMapper, you're in the right place. Browse the Repeaters appear on the map once their adverts are heard through a connected observer. Try the following: - Force an advert from your repeater. - - Confirm the region has at least one active observer by checking **Region Info > Observers** from the map. A repeaters advert must be picked up by one of these observers. If observers are missing, contact your region's administrator, as they may have a whitelist of observers from which to ingest from configured. + - Confirm the region has at least one active observer by opening **Region → Observers** on the map. A repeater's advert must be picked up by one of these observers. If observers are missing, contact your region's administrator, as the region may only accept data from a list of chosen observers. - If the repeater or observer was recently added, give it a few minutes to be picked up. - - Ensure the repeater has location coordinates configured. - - The region may have the option "New Repeaters Enter Pending State" enabled (check through the **Region Info** page), in which event the region administrator will need to approve the repeater before it is added. - - Repeaters that are well outside of a regions defined radius may not get added to the map as an anti-spam/anti-misconfiguration measure. Please check with your region's administrator. + - Ensure the repeater has a name and location coordinates configured. Repeaters without a location are recorded but not placed on the map. + - The region may have **New Repeaters Enter Pending** enabled (shown in **Region → Region Info**), in which case the region administrator must approve the repeater before it appears. + - Repeaters well outside a region's area may not be added to the map, as an anti-spam/anti-misconfiguration measure. Please check with your region's administrator. - If your repeater or room server is also an observer, it may not "hear" its own advert. Another observer must be within range in order to ingest it's advert and display on the map. If there are no other observers nearby, you can mimic the repeaters advert from a companion by using the MeshCore app, select the ellipses beside the repeater, select "Share", and then select "Zero Hop Advert". When this is the case, however, this repeater will eventually become stale and get removed. This process must be repeated regularly. + If your repeater or room server is also an observer, it may not "hear" its own advert. Another observer must be within range to pick up its advert and display it on the map. If there are no other observers nearby, you can relay the repeater's advert from a companion by using the MeshCore app, select the ellipses beside the repeater, select "Share", and then select "Zero Hop Advert". When this is the case, however, this repeater will eventually become stale and get removed. This process must be repeated regularly. If it still doesn't appear, contact your region's administrator.
-??? question "My repeater shows as Excluded or Duplicate." - As a region's mesh network grows, the likelihood of two repeaters sharing the same short ID increases. MeshMapper detects these collisions and disables affected repeaters to protect data integrity. See [Duplicate Repeater IDs](https://wiki.meshmapper.net/duplicaterepeaterid/) for a full explanation and resolution steps. +??? question "My repeater shows as Ambiguous." + As a region's mesh network grows, two repeaters can end up sharing the same short ID. When MeshMapper can't tell your repeater apart from another at the ID width it advertises, it marks it **Ambiguous**, because pings can't be credited to it with certainty. See [Duplicate Repeater IDs](duplicaterepeaterid.md) for a full explanation and how to fix it.
@@ -32,31 +32,35 @@ If you're having trouble with MeshMapper, you're in the right place. Browse the Large regions with lots of data can be demanding on older devices or slow connections. Try the following: - **Coverage Only Mode**: A "Switch to Coverage Only" button appears on the loading screen. This loads just the coverage grid without the interactive data, significantly reducing resource usage. - - **Grid Mode**: Use the "Simplified" grid mode (300m cells) from within the map settings instead of "Detailed" (100m cells). - - **Filter by time**: Use the Filter panel to limit data to a recent time range (e.g. Last 30 days). + - **Grid Mode**: Use **Simplified** (300 m squares) instead of **Detailed** (100 m) under **Grid Mode** in [Settings](layers.md#settings). + - **Filter by time**: Use **Filter → Time → Show data from** to limit data to a recent range (e.g. Last 30 days).
??? question "Grid squares are showing unexpected colours." Grid square colours depend on the active **Coverage Mode**: - - **Standard**: Colours represent ping type (green=BIDIR, orange=TX, purple=RX, etc.) + - **Standard**: Colours represent ping type (green=BIDIR, cyan=DISC/TRACE, orange=TX, purple=RX, grey=DEAD, red=DROP) - **Effective Coverage**: Averaged quality score (green=high quality, red=low quality) - **Signal Strength**: Based on SNR (green=strong, red=weak) - **Ping Age**: Based on data recency (green=recent, red=stale) - **Noise Floor**: Based on RF noise relative to each companion's baseline (green=quiet, red=loud) Check which mode is selected in the **Coverage Mode** section of the Layer Control. + + If data seems to be missing, also check the **Freq** radio preset in the navigation bar, **Hide Missing-Repeater Data** in Settings, and any active filters (such as **ID width**).
-
-??? question "The Live Analyzer isn't drawing lines between some repeaters, or otherwise doesn't appear to be showing all packet paths." - The Live Visualization mode in the Packet Analyzer can only draw lines/paths between repeaters that are **not** in a duplicate or conflict state. Because duplicate repeaters share the same identifier, the system cannot determine which physical repeater was actually involved in the packet path, so lines are not drawn to avoid displaying misleading information. This is the same duplicate detection logic that applies elsewhere in MeshMapper. +
+??? question "Visualize Live isn't drawing lines between some repeaters, or doesn't seem to show all packet paths." + **Insights → Visualize Live** can only draw paths through repeaters whose ID matches exactly one repeater. Hops through **Ambiguous** repeaters (IDs shared with another repeater) are skipped, because MeshMapper can't tell which repeater was actually involved. This is the same logic used elsewhere in MeshMapper; see [The Rules](duplicaterepeaterid.md#the-rules).
??? question "I'm not seeing repeater neighbours, or the associations are old (orange)." - MeshMapper determines a repeater's neighbours using the hop information contained in repeater adverts, contact adverts, or wardriving pings. These packets will need to travel between two or repeaters before getting ingested by an observer. For example, an advert that goes directly from repeater to observer has no hops, therefore no neighbour information is available. However, if that same advert hops to a different repeater first and then to the observer, one neighbour association can be made. The more observers and repeaters a region has, the greater the possibility packets will jump around between repeaters and record hop/neighbour information. + MeshMapper works out a repeater's neighbours from the paths of packets its observers hear. A packet needs to travel between two or more repeaters before reaching an observer. For example, an advert that goes directly from repeater to observer has no hops, therefore no neighbour information is available. However, if that same advert hops to a different repeater first and then to the observer, one neighbour association can be made. The more observers and repeaters a region has, the more neighbour information is recorded. + + Neighbour lines are **green** when seen in the last 3 days and **orange** when older; they disappear once the region's retention window closes. Repeaters can also report their neighbours directly (**blue**), or a wardriver's app can upload them (**purple**). Links to Ambiguous repeaters aren't drawn. See [Links Between Repeaters](visuals.md#links-between-repeaters).
--- @@ -73,12 +77,12 @@ If you're having trouble with MeshMapper, you're in the right place. Browse the 4. Restart the MeshMapper app. 5. If pairing fails repeatedly, remove the device from your phone's Bluetooth settings and re-pair. - See the [Connection Guide](https://wiki.meshmapper.net/app_connection_guide/) for detailed pairing instructions. + See the [Connection Guide](app_connection_guide.md) for detailed pairing instructions.
??? question "The app says I'm outside of a region." - You need to be within a registered MeshMapper region to start a wardriving session. If there isn't a region near you, you can [request one](https://wiki.meshmapper.net/onboarding). + You need to be within a registered MeshMapper region to start a wardriving session. If there isn't a region near you, you can [request one](onboarding.md).
@@ -87,7 +91,7 @@ If you're having trouble with MeshMapper, you're in the right place. Browse the - Ensure location permissions are granted to the MeshMapper app. - Move to an area with a clear view of the sky (away from tall buildings or dense tree cover). - - Wait a minute or two for the GPS to get a solid fix before starting a session. + - Wait a minute or two for the GPS to get a solid fix before starting a session. Fixes less accurate than 50 m are rejected. - On Android, ensure location mode is set to "High accuracy."
@@ -97,7 +101,9 @@ If you're having trouble with MeshMapper, you're in the right place. Browse the
??? question "I can't access the admin portal." - The admin portal is only available to region administrators. If you believe you should have access, confirm with the person who set up the region or contact a Moderator on Discord. See the [Administrator List](https://wiki.meshmapper.net/administratorlist/) to find your region's admin. + The admin panel (**Region → Admin Panel** on the map) is only available to region administrators. Sign in with your My MeshMapper account, or with **Sign in with Discord**. Forgot your password? Use **Forgot password?** to reset it yourself. + + If you believe you should have access, confirm with the person who set up the region or contact a Moderator on Discord. See the [Administrator List](administratorlist.md) to find your region's admin.
@@ -106,9 +112,9 @@ If you're having trouble with MeshMapper, you're in the right place. Browse the 1. Check that the observer device is running and connected to the MQTT broker. 2. Verify the MQTT topic and credentials in your observer configuration. - 3. Check the **Observers** panel in Region Info to see if the observer is listed and its last-heard timestamp. + 3. Open **Region → Observers** on the map to see if the observer is listed and when it last reported. - See [MeshMapper MQTT Setup](https://wiki.meshmapper.net/mqtt-main/) for configuration details. + See [MeshMapper MQTT Setup](mqtt-main.md) for configuration details.
--- @@ -120,11 +126,11 @@ If you can't find the answer here, there are several ways to get support: - **Wiki**: Browse the full wiki documentation. - **AI Bot (@MeshMapper)**: The MeshMapper AI bot on Discord can answer many questions. Send it a DM, tag it in a public message, or reply to a message and tag it. - **Discord Community**: The MeshMapper community on Discord is knowledgeable and very helpful. Post your question in the appropriate channel and someone will be able to help you out. -- **Region Administrator**: For issues specific to your region (settings, configuration, etc.), reach out to your [region's administrator](https://wiki.meshmapper.net/administratorlist/). If they're unavailable, tag a `@Moderator` in the MeshMapper Discord server. Moderators (also known as Global Administrators) have access to assist any region. +- **Region Administrator**: For issues specific to your region (settings, configuration, etc.), reach out to your [region's administrator](administratorlist.md). If they're unavailable, tag a `@Moderator` in the MeshMapper Discord server. Moderators (also known as Global Administrators) have access to assist any region. ### Reporting Bugs -Notice a bug? You can submit a ticket using the guided form on the [Report Bugs & Features](https://wiki.meshmapper.net/reportbugs) page, or tag the MeshMapper AI bot on Discord with **`!bug`** followed by a description. +Notice a bug? You can submit a ticket using the guided form on the [Report Bugs & Features](reportbugs.md) page, or tag the MeshMapper AI bot on Discord with **`!bug`** followed by a description. ### Feature Requests diff --git a/docs/visuals.md b/docs/visuals.md index d38a990..22bf5f1 100755 --- a/docs/visuals.md +++ b/docs/visuals.md @@ -1,235 +1,176 @@ # Understanding Visuals -MeshMapper visualizes mesh coverage using a grid system, repeater chips, connecting lines, and detailed popups. This guide explains every mark on the map, in the same order as the **Legend** card in the bottom right corner. +This page explains every mark on a region map (grid squares, repeater chips, lines and the details panel), roughly in the order of the **Legend** card in the bottom-right corner. !!! note "Colours on this page are the Default palette" - Every colour named below is the Default one. MeshMapper also ships four colour vision palettes (Protanopia, Deuteranopia, Tritanopia and Achromatopsia) under **Settings > Accessibility > Colour Vision**, and each of them remaps these colours. Backbone gold, for example, becomes white in all four. See the [colour vision accessibility options](layers.md#accessibility) for the full list. Where a mark also has a distinctive shape or position, this page says so, so you can find it whichever palette you use. + MeshMapper also has four colour vision palettes (Protanopia, Deuteranopia, Tritanopia and Achromatopsia) under **Settings > Accessibility > Colour Vision**, and each one remaps these colours. Backbone gold, for example, becomes white in all four. See the [colour vision options](layers.md#accessibility). Where a mark also has a distinctive shape or position, this page says so. ## The Grid System -The map is divided into small grid squares. The grid size is **300m x 300m** in Simplified mode and **100m x 100m** in Detailed mode — switch between the two via the **Grid Mode** option in the Settings panel. +The map is divided into grid squares: **300 m** in **Simplified** mode and **100 m** in **Detailed** mode (change it with **Grid Mode** in [Settings](layers.md#settings)). In Detailed mode each ping fills a 3×3 block of squares around where it was sent. -Since a single grid square may contain multiple pings from different times or users, MeshMapper uses a **Priority System** to determine which colour to display. The map will always show the "best" result available for that location. +A square can hold many pings, so it shows the **best** result it has, in this order: -| Priority | Colour | Meaning | +| Priority | Colour | Type | | --- | --- | --- | -| **1 (Highest)** | **Green** | **BIDIR** (Bidirectional) - Confirmed two-way coverage. | -| **2** | **Cyan** | **DISC** (Discovery) - Discovery packet sent and reply heard. | -| **3** | **Orange** | **TX** (Transmit) - Message sent, but no repeat was heard. | -| **4** | **Purple** | **RX** (Receive) - Heard traffic while in RX mode. | -| **5** | **Grey** | **DEAD** - Repeater heard the ping, but it did not make it into the wider mesh | -| **6 (Lowest)** | **Red** | **DROP** - Failed ping. No repeats heard, did not make it into the wider mesh. | +| **1 (Highest)** | **Green** | BIDIR | +| **2** | **Cyan** | DISC / TRACE | +| **3** | **Orange** | TX | +| **4** | **Purple** | RX | +| **5** | **Grey** | DEAD | +| **6 (Lowest)** | **Red** | DROP | -*Example:* If a grid square contains 10 failed pings (Red) and 1 successful ping (Green), the square will appear **Green** to indicate that coverage is possible at that location. +*Example:* A square with 10 red pings and 1 green ping shows **green**, because coverage is possible there. -## Ping Types Defined - -Here is a detailed breakdown of the different coverage statuses: - - - **BIDIRECTIONAL (BIDIR)** - *Green* - - You sent a message, it was received by a repeater, and your radio heard the repeater send it back. - - This confirms a solid two-way link. - - - **DISCOVERY (DISC)** - *Cyan* - - Your radio sent a specialized "Discovery" packet, and a node responded. - - **TRACE** packets are shown as DISC as well. +Clicking a square highlights it and dims the rest of the coverage. The other [coverage modes](layers.md#coverage-modes) (Effective Coverage, Signal Strength, Ping Age, Noise Floor) colour squares differently and each has its own legend. - - **TRANSMIT (TX)** - *Orange* - - Your message was successfully sent into the mesh (it reached a repeater), but your radio did not hear the confirmation repeat. - - This often happens when you have a high-power transmitter but a lower-gain antenna for receiving, or if the repeater is far away. - - - **RECEIVE (RX)** - *Purple* - - Your radio heard packets from the mesh (e.g., other users, telemetry), but you did not transmit. - - Useful for mapping where the mesh can be heard, even if you cannot reach it. +## Ping Types Defined +What decides a ping's type is whether your radio heard a repeat, and whether the ping reached MeshMapper's observers. + + - **BIDIR** - *Green* + - Heard repeats from the mesh **and** successfully routed through it. A solid two-way link. + - **DISC** - *Cyan* + - Your radio sent a discovery request and heard a repeater reply. + - **TRACE** - *Cyan* + - Your radio sent a trace and heard the reply. Shown the same as DISC on the map. + - **TX** - *Orange* + - Successfully routed through the mesh, but your radio heard no repeats back. Often a sign you can reach the mesh but can't hear it well. + - **RX** - *Purple* + - Your radio heard mesh traffic but didn't transmit. Useful for mapping where the mesh can be heard. - **DEAD** - *Grey* - - A repeater heard your signal, but the message didn't go anywhere (it wasn't repeated to the rest of the mesh). - - This usually indicates a "Zombie" repeater, a misconfigured repeater that is receiving but not routing, or the repeater does not have a reliable connection into the wider mesh. - + - A repeater heard it, but no other radio received the repeat. Often a repeater that isn't well connected to the wider mesh. - **DROP** - *Red* - - You sent a message, but no repeaters heard it, and no route was established. - - Indicates a dead zone or lack of coverage. - -One more square colour is not a ping type at all: + - No repeats heard **and** no successful route. A likely dead zone. - - **Selected** - *Bright Blue* (`#007bff`) - - The grid square or ping you have clicked. It replaces that square's normal colour for as long as it is selected. - -![Diagram](https://meshmapper.net/img/pingtypes.png) +![How MeshMapper decides a ping's type: whether a repeater heard you, whether you heard its repeat, and whether the ping reached MeshMapper's observers.](assets/ping-types.svg) ## Repeaters -**Ghost** means a ping identified a repeater by its full key, but that repeater has never been registered on this map, so MeshMapper does not know where to draw it. **Gone** means a repeater that was placed earlier can no longer be resolved for that ping. Neither label is a separate ping type. Ask a region admin to check the repeater's adverts and current record before changing coverage data. - ### Chip Anatomy -A repeater is drawn as a small dark rounded chip carrying its hex ID: +A repeater is drawn as a small dark chip carrying its hex ID (at the width it advertises, 1–3 bytes): - - The **body** is always the same neutral dark slate (`#22303A`), on every state and in every colour vision palette. - - The **state** is carried on a thick bar down the **left edge** of the chip, and on the chip's border. - - The **ID label** is white on every state. + - The **body** is always dark slate, in every state and palette. + - The **state** is shown by a thick bar down the **left edge** and the chip's border. + - The **ID** is always white. -So the thing to scan for is the **edge colour**, not a coloured blob. There is no solid coloured dot on the map any more. +Scan for the **edge colour**. ### Repeater States | State | Edge Colour | Meaning | | --- | --- | --- | -| **Active** | **Green** (`#2BB673`) | Heard from recently. This is the ordinary state. | -| **New** | **Pink** (`#FF4D9D`) | First seen by MeshMapper in the last 14 days. Drawn slightly larger, with a glow. | -| **Aged** | **Grey** (`#8A97A3`) | Has not sent an advert within the window its region administrator set (24 hours unless they changed it). | -| **Ambiguous ID** | **Red** (`#E0565B`) | Its ID overlaps another repeater at the width it advertises, so pings cannot be attributed to it with certainty. See [Duplicate Repeater IDs](duplicaterepeaterid.md). | -| **Backbone site** | **Gold** (`#E8B923`) | One of the repeaters carrying the most traffic. See [The Backbone](#the-backbone). | +| **Active** | **Green** | Heard from recently. The ordinary state. | +| **New** | **Pink** | First seen in the last 14 days. Drawn slightly larger, with a glow. | +| **Stale** | **Grey** | No advert within the region's window (24 hours unless the admin changed it). | +| **Ambiguous** | **Red** | Its ID matches another repeater's at the width it advertises, so pings can't be credited to it with certainty. See [Duplicate Repeater IDs](duplicaterepeaterid.md). | +| **Backbone site** | **Gold** | One of the repeaters carrying the most traffic. See [The Backbone](#the-backbone). | -### Observers +If more than one applies, **Ambiguous** wins over **Stale**, which wins over **New**. So a new repeater that has gone quiet shows grey, not pink. Gold only replaces **Active**. -An **observer** is a repeater that also feeds packets to MeshMapper. Its chip carries an eye glyph (👁) in front of the ID. +### Observers -The eye is a marker, not a state. It rides on top of whatever colour the chip already has, so an observer can be Active, New, Aged or Ambiguous at the same time. +An **observer** is a repeater that also feeds packets to MeshMapper. Its chip has an eye (👁) in front of the ID. The eye isn't a state, so an observer can be in any of the states above. ### Groups -When repeaters are too close together to draw apart, they collapse into a round dark **badge**: +In **Simplified** mode, repeaters too close together to draw apart collapse into a round **badge**: - - The **number** is how many repeaters are in the group. Past 1000 it is abbreviated, for example `1.4k`. - - The **ring** around the badge is the colour of the state the most of them are in. It is whichever state is commonest, which is not necessarily more than half of them. - - The **row of dots** underneath is one dot per state **present** in the group, so a badge with three dots holds repeaters in three different states. The dots are all the same size and say nothing about how many. + - The **number** is how many repeaters are in it (e.g. `1.4k` past 1000). + - The **ring** is the colour of the most common state in the group. + - The **dots** underneath show which states are present, one dot per state. They don't show how many. -**A badge is clickable, which is not obvious.** Clicking it **fans the members out** on spider legs so you can reach a repeater buried in a stack. If the group is both large (more than 18 repeaters) and you are zoomed well out (below zoom 14), it **zooms in** instead. Either way a group can always be opened. +**Click a badge** to fan the repeaters out. Large groups (more than 18) zoom in instead when you're zoomed well out. + +Badges aren't used in **Detailed** mode, or while Repeater Neighbours, Repeater Scopes, Backbone or Visualize Live is on. ## Links Between Repeaters -The **Repeater Neighbours** overlay in the Layers control draws lines between repeaters that are known to reach each other. There are four kinds, and one more line that only appears when a popup is open. All of them are drawn solid, so the colour is what tells them apart. +The **Repeater Neighbours** overlay draws lines between repeaters known to reach each other. All are solid, so the colour tells them apart. | Line Colour | Kind | Meaning | | --- | --- | --- | -| **Green** (`#28a745`) | Inferred, fresh | Seen next to each other in a packet path an observer heard, within the last 3 days. | -| **Orange** (`#fd7e14`) | Inferred, older | The same, but older than 3 days. The line disappears once the region's retention window closes, which is 7 days unless the region administrator changed it. | -| **Blue** (`#1e88e5`) | Reported | The repeater reported them as a direct neighbour over the air. | -| **Purple** (`#8e24aa`) | Uploaded | An admin pulled the repeater's neighbour table and uploaded it from the app. | -| **Dark Blue** (`#00008b`) | Route path | The one-way route a packet actually took. This one is drawn when you open a ping popup, not by the overlay. | +| **Green** | Inferred, fresh | Seen next to each other in a packet path an observer heard, in the last 3 days. | +| **Orange** | Inferred, older | The same, but older than 3 days. Hidden after 7 days (unless the admin changed it). | +| **Blue** | Reported | The repeater reported the other as a neighbour when an observer asked. Kept 30 days by default. | +| **Purple** | Uploaded | A wardriver's app collected the repeater's neighbour table and uploaded it. Kept until replaced. | + +If a pair has a Reported or Uploaded link, the inferred line for that pair isn't drawn. -A **Reported** or **Uploaded** line takes over from an inferred one: if a pair of repeaters has a reported or uploaded link, the green or orange line for that same pair is not drawn. +The **Repeater Scopes** overlay uses the same blue and purple, but shows inferred links in **grey**. See [Repeater Scopes](layers.md#repeater-scopes). !!! note "Orange means two different things" - An orange **square** is a TX ping. An orange **line** is an older inferred neighbour link. They are unrelated. + An orange **square** is a TX ping. An orange **line** is an older inferred neighbour link. ## The Backbone -**Backbone** is an overlay you switch on in the Layers control. It answers one question: which handful of repeaters is this region actually leaning on? - -The backbone is the **smallest set of repeaters whose links together carry half the region's traffic**. It is measured from inferred links, the ones observers heard, because those are the only links that carry a count. In most regions it comes out at a dozen or two sites. - -### Reading the Percentages +The **Backbone** overlay shows the repeaters the region leans on most: the smallest set whose links carry **half** of the region's traffic. For how it's calculated, see [Backbone](backbone.md). -Each backbone chip's label carries **its own share** of the region's traffic, for example `A1B2 7.4%`. - -**Those shares add up.** Nine chips reading 12%, 9% and 7% are not slices of one bigger number, they sum to roughly the half that defines the backbone. This is the easiest thing on the map to misread. - -The gold stamp and the percentage are shown whether or not the Backbone overlay is switched on. - -### Gold Does Not Mean Healthy - -Gold replaces **Active** and nothing else. A backbone repeater that is New, Aged or Ambiguous keeps its own colour and is still in the backbone set. - -This is deliberate: importance must never hide health. It also means **"the gold repeaters are the backbone" is wrong**. Some backbone sites are pink, grey or red. - -### Trunks - -**Trunks** are the lines drawn between backbone sites. Each site keeps its three busiest links. - -A trunk's colour is its **rank band** among all the trunks on the map, busiest to quietest, on a five step ramp: - -| Band | Colour | -| --- | --- | -| Busiest | `#ff3b30` | -| | `#ff8c1a` | -| | `#f5b301` | -| | `#f5d06f` | -| Quietest | `#ffe9a8` | - -It is a **rank, not a value**, so the colours say which trunks are busier than which, not how much traffic any of them carries. **The line width means nothing**, and the colours do not change as you pan or zoom. - -### What the Overlay Does - -Switching Backbone on hides every repeater that is not a backbone site, turns the Repeaters layer on if it was off, and switches Repeater Neighbours off. The two overlays cannot be on at once. - -### On a Group Map - -**A group is scored as one pool.** On a multi-region group map the whole group is treated like a single region, so a chip's share is its share of the group's combined traffic. A small member region ending up with two backbone sites, or none at all, is the correct answer rather than a bug. + - **Percentages**: each backbone chip shows **its own share** of the region's traffic (e.g. `A1B2 7.4%`). The shares **add up** to about half; they aren't slices of one number. Chips show their share even with the overlay off. + - **Gold doesn't mean healthy**: gold only replaces Active. A backbone repeater that's New, Stale or Ambiguous keeps that colour, so not every backbone site is gold. + - **Trunks**: lines between backbone sites. Each site keeps its three busiest links. The colour is the trunk's **rank**, busiest (red) to quietest (pale yellow), not an amount of traffic. Line width means nothing. + - **Turning it on** shows only backbone repeaters, turns **Repeaters** on, and turns **Repeater Neighbours** and **Repeater Scopes** off. + - **On a group map**, the whole group is scored as one pool, so a small member region may have two backbone sites or none. ## Signal (SNR) -Where the map colours something by signal quality, it uses three bands: +Wherever the map colours something by signal quality, it uses three bands: | Band | Colour | Quality | | --- | --- | --- | -| **Over 5 dB** | **Green** (`#1e7e34`) | Strong | -| **-1 to 5 dB** | **Dark Yellow** (`#856404`) | Moderate | -| **Under -1 dB** | **Red** (`#bd2130`) | Weak | +| **Over 5 dB** | **Green** | Strong | +| **-1 to 5 dB** | **Dark Yellow** | Moderate | +| **Under -1 dB** | **Red** | Weak | -If the signal value cannot be read, the mark is drawn in a neutral **Grey** (`#6c757d`) instead. +If the signal can't be read, it's shown in **grey**. -## Popups & Data +## Ping Details -Clicking on a grid square opens a popup with detailed information. +Click a grid square to see its pings. By default details open in the **Sidebar**; you can switch to **Popup** under **Info Panel** in [Settings](layers.md#settings). -### 1. Summary View +### Summary -If a grid square contains multiple pings, the popup opens in **Summary View** first. - - **Counts**: Shows the total number of pings for each type (BIDIR, TX, etc.) in that square. - - **Averages**: Displays the Average SNR (Signal-to-Noise Ratio) and Average Noise Floor. - - **Max Range**: Shows the furthest distance achieved from a repeater in this square. +When a square has more than one ping, you see a summary first: **Total Pings**, a count for each type, the average signal (**AVG SNR**), the furthest distance to a repeater (**MAX DIST**) and the average noise floor (**AVG NOISE**). -### 2. Detail View -You can cycle through individual pings using the **<** and **>** buttons at the bottom of the popup, arranged by the newest data first. + - **Sidebar**: below the summary is a **Ping History** list, newest first. Click a card to see that ping. + - **Popup**: use the **<** and **>** buttons to step through pings, newest first. - - **Identity**: Who sent the ping (if not hidden via region settings). - - **Time**: Date and time of the ping. - - **Telemetry**: - - **Power**: Transmit power used (e.g., 0.6W). - - **Ext. Ant**: Indicates if an external antenna was used. - - **Path**: - - **Heard Repeats**: A list of all repeaters your radio heard re-broadcasting your message, sorted by signal strength (SNR). - - **Via**: The first repeaters responsible for transmitting your coverage data to MeshMapper. +### A Single Ping -### 3. Visual Lines -When a popup is open, MeshMapper draws lines on the map to visualize the connection: + - **Type**, **time** and who sent it (unless the region hides names). + - **Power**, and whether an **external antenna** was used. + - **Radio preset** (frequency / bandwidth / SF / CR). + - **Heard Repeats**: every repeater your radio heard repeat the ping, strongest signal first. For DISC and TRACE this shows the repeater that replied, with local and remote signal. + - **Via**: the repeaters that carried the ping to MeshMapper's observers. + - A repeater shown as **(AMBIGUOUS)** lists its possible **Candidates**. One shown as **(hidden)** is a [private repeater](layers.md#private-repeaters). + - **Ghost** means the ping named a repeater that has never been registered on this map. **Gone** means a repeater that was placed before can no longer be matched (for example, it has moved). + - The **link icon** copies a direct link to that ping. - - **Solid Coloured Line**: Represents the signal your radio **Heard** from a repeater. The colour indicates signal strength (Green = Good, Dark Yellow = Okay, Red = Weak), using the [Signal (SNR)](#signal-snr) bands above. - - **Dark Blue Line**: Represents the one-way **Via** path, also called the route path. - - **Red Line**: Indicates a connection to a **Duplicate/Excluded** repeater. Its label reads `Duplicate` above the distance. +### Lines on the Map -### 4. Sharing +While a ping is selected, lines show how it connected: -Every popup includes a **Link Icon** (chain link) in the top-right corner. Clicking this copies a direct URL to that specific grid square or ping to your clipboard, allowing you to share exact locations with others. + - **Solid coloured line**: a repeater your radio **heard**, coloured by [signal](#signal-snr). + - **Dark blue line**: the **Via** route the ping took. + - **Red line** labelled **Duplicate**: a possible repeater when the ID is ambiguous. -## Repeater Popups +## Repeater Details -Clicking on a repeater chip opens a popup with details: +Click a repeater chip to see its details. The rest of the coverage dims so its own coverage stands out (see **Repeater Coverage** in [Overlays](layers.md#overlays)). - - **Status Indicators**: - - **Repeater Online**: The repeater has been heard from recently. - - **New Repeater (Pink)**: First seen within the last 14 days. - - **Aged Repeater (Grey)**: Has not been heard from in a specific timeframe set by the region administrator (e.g., 24 hours). - - **Ambiguous (Red)**: The repeater's ID collides with another repeater at its byte width. - - A red warning row appears if the repeater's clock is off by more than 120 seconds ("Repeater time is not set correctly"). - - **Details**: - - **ID**: The repeater's identifier (shown at its advertised byte width), plus its power and **Advert Bytes** (the ID width the repeater advertises). - - **First Heard**: The date the repeater was first discovered by MeshMapper. - - **Last Heard**: The exact time the repeater was last seen by the mesh. - - **Max Range**: The furthest distance a user has successfully connected to this repeater from. - - **Stats & Chart**: Per-type ping counts (BIDIR / TX / RX / DISC / DEAD) and a signal-vs-distance chart built from the repeater's coverage data. - - **Neighbours**: A list of other repeaters this node has been linked to, with the source of each link marked **I** (inferred), **R** (reported) or **U** (uploaded). See [Links Between Repeaters](#links-between-repeaters). - - **Add Another**: Compare mode — select additional repeaters to view their coverage side by side. - - **Copy Link**: A link icon in the top right allows you to copy a direct URL to this repeater. - -While a repeater is selected, the rest of the coverage grid dims so the selected repeater's own coverage stands out. + - **Status**: Repeater Online, Backbone Site, New Repeater, Stale Repeater, Ambiguous (with the other repeaters sharing its ID), Inactive or Disabled. + - **Clock warning**: "Repeater time is not set correctly" if its clock was more than 120 seconds off when last checked in the past week. + - **Details**: ID and advertised ID width (**Advert Bytes**), power, **First Heard**, **Last Heard**, **Max Range**, and any hardware, antenna, height, power source and site notes the admins have added. + - **Freq**: the radio presets it has been heard on. + - **Mesh Scopes**: the scopes it carries. See [Repeater Scopes](layers.md#repeater-scopes). + - **Traffic rank**: where it ranks for traffic in the region, and its share. + - **Stats**: ping counts by type and a signal-vs-distance chart. + - **Neighbours**: repeaters it links to, marked **I** (inferred), **R** (reported) or **U** (uploaded), with direction, signal each way, packet count and last seen. Click one to draw that link. + - **Recent Adverts** (sidebar): its adverts from the last 7 days. + - **Add Another** (sidebar): compare several repeaters' coverage side by side. + - The **link icon** copies a direct link to the repeater. ## Private Repeaters -If a repeater's name ends with the "no entry" emoji (🚫), it is treated as a **Private Repeater**: - - - **Map**: The repeater's Name, Location, and ID are completely removed from the map. - - **Pings**: Coverage data is still kept and displayed on the grid, but the repeater's identity in the popup is masked as `(hidden)`. - - **Leaderboards**: The repeater's name is replaced with "(private repeater)", though its statistics are still calculated and ranked. +Repeaters whose name starts or ends with 🚫 are hidden from the map. See [Private Repeaters](layers.md#private-repeaters). diff --git a/docs/webhooks.md b/docs/webhooks.md index 4411ae1..81d22cc 100644 --- a/docs/webhooks.md +++ b/docs/webhooks.md @@ -6,14 +6,16 @@ Webhooks work alongside Discord DM notifications — enabling a webhook does not ## Setup -1. Navigate to the **Admin Portal** → **Settings** tab for your region. -2. In the **Webhook Notifications** section, enter your webhook URL. +1. Open your region's admin panel and go to the **Settings** tab. +2. In the **Notifications** section, enter your **Webhook URL**. 3. Select which events should trigger a webhook notification. -4. Click **Save Settings**. -5. Use the **Send Test** button to verify your endpoint receives the test payload. +4. Click **Save All Settings**. +5. Use the **Send Test** button to check your endpoint receives the test payload. (It tests the URL as typed, even before saving.) + +For a region in a [multiregion group](multiregions.md), the group admin can set a separate webhook for each region in the group settings. !!! warning "HTTPS Required" - Only HTTPS URLs are accepted. HTTP, internal, and private network URLs are blocked for security. + Only HTTPS URLs are accepted. HTTP, internal, and private network URLs are blocked for security, and a non-HTTPS URL is cleared when you save. ## Events @@ -21,10 +23,12 @@ You can enable or disable each event type individually: | Event | Description | |-------|-------------| -| **Duplicate Repeater ID** | A new repeater has been detected with an ID that collides with an existing repeater, putting both into Excluded status. | +| **Ambiguous Repeater ID** | Two or more repeaters share an ID, so one or more were marked Ambiguous. See [Duplicate Repeater IDs](duplicaterepeaterid.md). | | **Pending Repeater** | Your region has repeaters in Pending state awaiting admin review. Checked once daily. | -| **Offline Observer** | One or more MQTT observers in your region may be offline. Checked once daily. | +| **Offline Observer** | One or more MQTT observers in your region may be offline. | | **Visitor Message** | A visitor has sent a message to your region's administrators via the map. | +| **Suspicious Flight** | A wardriving session in your region moved faster than ground travel allows. Checked once daily. | +| **Pending Repeater Link** | Pings were held for review instead of being linked to a repeater that's unusually far away. Checked once daily. | By default, all events are enabled when a webhook URL is configured. @@ -37,28 +41,28 @@ Every webhook sends an HTTP POST request with a JSON body. The structure is cons "event": "duplicate_repeater", "region": "YOW", "timestamp": 1744123456, - "message": "New ID collision detected on YOW.\n\nCollision Group: A1\n\nRepeaters:\nRepeaterA (A1B2C3D4)\nRepeaterB (A1E5F6G7)", + "message": "**New Ambiguous Repeater ID Detected on YOW.**\n\n**Shared ID prefix:** `A1` (1-byte)\n\n**Repeaters:**\n[EXCLUDED] RepeaterA — 1-byte ID (A1B2C3D4)\n[ACTIVE] RepeaterB — 1-byte ID (A1E5F6A7)", "data": { "collision_group": "A1", - "repeaters": ["RepeaterA (A1B2C3D4)", "RepeaterB (A1E5F6G7)"] + "repeaters": ["[EXCLUDED] RepeaterA — 1-byte ID (A1B2C3D4)", "[ACTIVE] RepeaterB — 1-byte ID (A1E5F6A7)"] } } ``` ### Fields -- **event** — The event type (e.g., `duplicate_repeater`, `pending_repeater`, `offline_observer`, `visitor_message`, `test`). +- **event** — The event type: `duplicate_repeater`, `pending_repeater`, `offline_observer`, `visitor_message`, `suspicious_flight`, `pending_link` or `test`. - **region** — The region code (e.g., `YOW`). -- **timestamp** — Unix timestamp of when the event occurred. -- **message** — A human-readable summary of the event. This is the same text sent via Discord DM, so simple integrations can use it directly. +- **timestamp** — Unix timestamp of when the webhook was sent. +- **message** — A readable summary using Discord markdown, mostly the same text as the Discord DM, so simple integrations can use it directly. - **data** — Event-specific structured data (see below). ### Event-Specific Data **duplicate_repeater:** -- `collision_group` — The ID that collided (e.g., `A1`). -- `repeaters` — Array of repeater names and IDs involved in the collision. +- `collision_group` — The shared ID prefix (1–3 bytes, e.g. `A1`). +- `repeaters` — Array of the repeaters sharing it, each marked `[EXCLUDED]` or `[ACTIVE]`. **pending_repeater:** @@ -72,6 +76,14 @@ Every webhook sends an HTTP POST request with a JSON body. The structure is cons - `body` — The full text of the visitor's message. +**suspicious_flight:** + +- `sessions` — Array of the session IDs flagged. + +**pending_link:** + +- `repeaters` — Array of the repeater IDs with held pings. + **test:** - `info` — A static test string confirming the webhook is working. @@ -85,9 +97,9 @@ Every webhook sends an HTTP POST request with a JSON body. The structure is cons - Check that the URL is reachable from the MeshMapper server. - Use the **Send Test** button to isolate the issue. -**Test button shows "Failed":** +**Test button doesn't show "Sent!":** -- The endpoint may be unreachable, returning an error status code, or timing out (3-second limit). +- It shows the error or the HTTP status code instead. The endpoint may be unreachable, returning an error, or timing out (3-second limit). - Verify the URL is correct and the endpoint is accepting POST requests with JSON content. **Receiving duplicate notifications:** @@ -98,4 +110,6 @@ Every webhook sends an HTTP POST request with a JSON body. The structure is cons - Webhook requests use HTTP POST with `Content-Type: application/json`. - Requests have a 3-second timeout and do not follow redirects. -- Failed webhook deliveries do not retry. +- Failed notifications are not re-sent. +- After a temporary error (timeout, network error, HTTP 408, 425, 429 or 5xx), the webhook pauses for 5 minutes, doubling up to 6 hours (a `Retry-After` header is respected). Events during the pause are skipped. +- After 3 permanent errors in a row, the webhook is switched off and a warning appears in Settings. A successful **Send Test** or a new URL switches it back on. diff --git a/docs/zones-api.md b/docs/zones-api.md index 75c4530..a755f4c 100644 --- a/docs/zones-api.md +++ b/docs/zones-api.md @@ -22,7 +22,7 @@ GET https://meshmapper.net/get_zones.php?country=CA | --- | --- | --- | | `country` | Yes | Two-letter country code (ISO 3166-1 alpha-2, e.g. `CA`, `US`, `GB`). Case doesn't matter. | -Only enabled regions are listed. Regions that are pending or turned off never appear. +Only enabled regions are listed. Regions that are pending or turned off never appear. A well-formed `country` with no regions returns 200 with `count: 0` and empty `zones` and `groups` arrays. ### Response @@ -53,18 +53,18 @@ Only enabled regions are listed. Regions that are pending or turned off never ap | Field | Description | | --- | --- | -| `code` | Region code, uppercase. Usually three letters, but can be 2 to 6 letters or digits. | +| `code` | Region code, uppercase, three letters or digits (e.g. `YOW`). | | `name` | Region name as MeshMapper stores it, including the country suffix. | | `short_name` | `name` without the `, CC` country suffix. | | `country` | Two-letter country code. | | `lat`, `lon` | The region's center point. | | `url` | The region's MeshMapper site. Append `get_geojson.php` for its boundary. | -| `has_boundary` | `true` when the region has a drawn boundary. When `false`, `get_geojson.php` returns the region with `geometry: null`. | -| `group` | The multi-region group this region belongs to (see [Multiregions](multiregions.md)), or `null`. | +| `has_boundary` | `true` when a boundary is stored for the region. When `false`, `get_geojson.php` returns the region with `geometry: null`. In rare cases a stored boundary can't be used, so `get_geojson.php` may still return `geometry: null` when this is `true`. | +| `group` | The first enabled group (lowest id) this region belongs to (see [Multiregions](multiregions.md)), or `null`. A region in several groups shows only one. | ### Group fields -`groups` lists each group that contains at least one of the listed regions. `members` is the group's full member list, which can include regions from other countries (`SEA` above). +`groups` lists the group shown in each listed region's `group` field. `members` is that group's enabled member list, which can include regions from other countries (`SEA` above). | Field | Description | | --- | --- | @@ -111,11 +111,14 @@ Returns a GeoJSON `FeatureCollection` ([RFC 7946](https://datatracker.ietf.org/d - Coordinates are `[longitude, latitude]`, as GeoJSON requires, rounded to 6 decimals (about 10 cm). The outline is never simplified. - The geometry is always a single `Polygon`. - A region with no drawn boundary has `"geometry": null` and `has_boundary: false`. MeshMapper doesn't draw a circle in its place, but `center` and `radius_km` are there if you want one. -- `center` is `[longitude, latitude]` too. +- `center` is `[longitude, latitude]` too. `radius_km` can be `null`. +- If the response is cut off mid-stream, the JSON is left unclosed on purpose. Treat a parse error as "retry". ## Caching -Both endpoints send `Cache-Control: public, max-age=3600` and an `ETag`. To check for changes cheaply, send the `ETag` back in `If-None-Match`; you'll get `304 Not Modified` with no body if nothing changed. `generated_at` changes on every response and isn't part of the `ETag`. +Both endpoints send `Cache-Control: public, max-age=3600` and an `ETag`. To check for changes cheaply, send the `ETag` back in `If-None-Match`; you'll get `304 Not Modified` with no body if nothing changed. `generated_at` changes on every response and isn't part of the `ETag`. A `304` still counts against the rate limit. + +Responses are gzip-compressed. ## Errors diff --git a/mkdocs.yml b/mkdocs.yml index 3352dd0..4133a81 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,6 @@ # Site Information site_name: MeshMapper Wiki -site_url: https://meshmapper.net +site_url: https://wiki.meshmapper.net/ site_description: Community-driven visualization and analytics platform for MeshCore LoRa mesh networks edit_uri: "" @@ -12,8 +12,9 @@ nav: - Onboarding New Regions: onboarding.md - MeshMapper MQTT Setup: - Overview: mqtt-main.md - - MeshCore Packet Capture: mqtt-python.md + - Native Firmware: mqtt-firmware.md - MeshCore-HA: mqtt-ha.md + - meshcoretomqtt: mqtt-python.md - PyMC Repeater: mqtt-pymc.md - Multiregions: multiregions.md