docs: document MeshMapper repeater import and node detail meshmapper field (#23)

This commit is contained in:
MrAlders0n authored and GitHub committed 2026-10-11 12:41:09 -04:00
1 parent 27319994ea
commit 7c1dff6fed
5 files changed
+73 -9

No files matched your search

+14
View File
@@ -111,6 +111,20 @@ ratelimit:
# channels:
# enabled: false
# refresh_interval: 24h # 24h-168h (one get_channels.php per region per 23.5h)
#
# Repeater site details (get_repeaters.php). Every known IATA that MeshMapper
# lists is fetched from its site, the same way as channels. Each repeater's
# admin-entered site details (power, hardware, antenna, heights, power source,
# notes), CARpeater flag, admin names, confirmed scopes and default scope are
# shown on node detail as `meshmapper`, matched by full public key. Positions,
# status and radio data are not imported. A failed refresh keeps the last good
# list and retries after 1h (or Retry-After); an empty list clears the region.
# Each request counts against the key's shared budget (1,000/day, 30/min), so
# 6h costs 4 requests per IATA per day. Turning it off deletes the import on
# restart. Logged under component=meshmapper.repeaters.
# repeaters:
# enabled: false
# refresh_interval: 6h # 1h-24h
iatas:
YVR:
@@ -112,6 +112,20 @@ ratelimit:
# channels:
# enabled: false
# refresh_interval: 24h # 24h-168h (one get_channels.php per region per 23.5h)
#
# Repeater site details (get_repeaters.php). Every known IATA that MeshMapper
# lists is fetched from its site, the same way as channels. Each repeater's
# admin-entered site details (power, hardware, antenna, heights, power source,
# notes), CARpeater flag, admin names, confirmed scopes and default scope are
# shown on node detail as `meshmapper`, matched by full public key. Positions,
# status and radio data are not imported. A failed refresh keeps the last good
# list and retries after 1h (or Retry-After); an empty list clears the region.
# Each request counts against the key's shared budget (1,000/day, 30/min), so
# 6h costs 4 requests per IATA per day. Turning it off deletes the import on
# restart. Logged under component=meshmapper.repeaters.
# repeaters:
# enabled: false
# refresh_interval: 6h # 1h-24h
iatas:
YVR:
+37 -1
View File
@@ -243,12 +243,48 @@ Adverts with a bad signature are not decoded and have no `parsedPayload`.
| Endpoint | Notes |
|---|---|
| `GET /nodes` | Page of node summaries. Cursor is `lastSeen` epoch ms. Default limit 50. |
| `GET /nodes/{nodeId}` | Node detail: capability flags, `minFirmwareVersion`, `iatas` (`[{iata, lastHeard}]`), `neighbors`, clock drift for repeaters and room servers. |
| `GET /nodes/{nodeId}` | Node detail: capability flags, `minFirmwareVersion`, `iatas` (`[{iata, lastHeard}]`), `neighbors`, clock drift for repeaters and room servers, and `meshmapper` when imported (see [MeshMapper repeater details](#meshmapper-repeater-details)). |
| `GET /nodes/{nodeId}/observations` | Page of observations of packets the node originated. Cursor is the observation ID. |
| `GET /nodes/{nodeId}/neighbors` | Plain array of neighbours: `{ id, name, publicKey, nodeType, nodeTypeName, lat, lng, iata, observationCount, firstSeen, lastSeen, snr }`. |
`/nodes` params: `type` (1 companion, 2 repeater, 3 room server, 4 sensor) or `typeName`, the location filters, `name` (partial, case-insensitive), `scope`, `pubkey` (exact hex), `pubkeyPrefix`, `supportsMultibytePaths`, `supportsMultibyteTraces`, `neighbors` (adds `neighborIds`), `cursor`, `limit`. Summaries include `stale` (not seen within `nodes.stale_threshold`) and, when `nodes.mark_foreign` is on, `possiblyForeign`.
#### MeshMapper repeater details
With `meshmapper.repeaters.enabled`, node detail carries `meshmapper` when MeshMapper's repeater
list has the node's full public key. It is omitted otherwise. Times are epoch ms; `fetchedAt` is
when Beacon last fetched the list. Text is admin-entered on MeshMapper, so escape it.
```json
"meshmapper": {
"iata": "YOW",
"fetchedAt": 1791234600000,
"site": {
"power": "1W", "hardware": "RAK4631", "antenna": "5.8 dBi fibreglass",
"heightM": 12, "heightAslM": 341.6, "powerSource": "solar",
"notes": "On the fire tower, east face"
},
"carpeater": false,
"admins": ["MrAlders0n"],
"scopes": [
{ "scope": "yow", "observedAt": 1791200000000, "observedPackets": 37, "proof": "multibyte", "reportedAt": 1791100000000 }
],
"scopesCheckedAt": 1791100000000,
"defaultScope": { "name": "yow", "state": "named", "updatedAt": 1791230000000, "source": "advert" }
}
```
- `site` is always an object; each field is omitted when unset. `powerSource` is `mains`,
`solar`, `battery` or `poe`. `heightAslM` can lag a new `heightM` by a few minutes.
- `carpeater` marks a repeater riding in a car: its position moves.
- `scopes` lists scopes MeshMapper confirmed it carrying. `proof` is `multibyte` or `floor`;
`observedAt`/`observedPackets` (seen forwarding), `reportedAt` (an observer asked it) and
`uploadedAt` (a wardriver's app asked it) are omitted for sources that never confirmed it.
`scopesCheckedAt` present with empty `scopes` means it answered with none.
- `defaultScope.state` is `named`, `unknown` (it sets one MeshMapper can't name yet) or
`none`; `name` is only sent when `named`; `source` is `advert` or `reported`. This is
MeshMapper's view; the top-level `defaultScope` is what Beacon matched from adverts.
#### Foreign repeater indication
With `nodes.mark_foreign: true`, repeater nodes carry `possiblyForeign`. It is `true` when the
+6 -6
View File
@@ -69,7 +69,7 @@ which ones to read.
| `log` | Log level and format. | You want JSON logs for a collector. |
| `server` | `trusted_proxies`: the proxy addresses allowed to tell Beacon the real client IP. | Always, if Beacon sits behind a proxy. See [Reverse proxy](reverse-proxy.md). |
| `ratelimit` | Per-client REST limits for `/api/v1/*`. On by default at 300 requests a minute. | You get 429s you did not expect. |
| `meshmapper` | Import transport scopes, IATA borders, region groups and public channels from MeshMapper instead of listing them by hand. Requires a [MeshMapper API key](#meshmapper-api-key). | You are in a region MeshMapper covers. |
| `meshmapper` | Import transport scopes, IATA borders, region groups and public channels from MeshMapper instead of listing them by hand, and add repeater site details to node detail. Requires a [MeshMapper API key](#meshmapper-api-key). | You are in a region MeshMapper covers. |
| `iatas` | Display names, coordinates and optional border files for airport codes. IATAs are created automatically when traffic arrives; this block only decorates them. A `borderFile` path is relative to `config.yaml`; in Docker the compose file mounts only `config.yaml`, so add a mount for the folder too (`- ./data/app/borders:/app/borders:ro` under the `app` service). | You want names on the map or a border drawn. |
| `regions` | Groups of IATAs with a name, map centre and zoom. | Always, unless MeshMapper imports them. |
| `channel_keys` | Hashtag channels and explicit keys for decrypting group messages. | Always. Without keys, channel messages are stored as hashes only. |
@@ -99,8 +99,9 @@ cannot honour. These are the ones people hit:
- `server.trusted_proxies` entries that are not CIDRs. One host is `10.0.0.5/32`, not `10.0.0.5`.
- `packets.retention` or `analytics.rollup_retention` under `24h`, or any negative duration
(`observers.delete_after` is the exception: zero or negative turns it off).
- MeshMapper refresh intervals outside their range: `scopes.refresh_interval` 1h to 24h,
`zones.refresh_interval` and `channels.refresh_interval` 24h to 168h.
- MeshMapper refresh intervals outside their range: `scopes.refresh_interval` and
`repeaters.refresh_interval` 1h to 24h, `zones.refresh_interval` and
`channels.refresh_interval` 24h to 168h.
- A `borderFile` that is missing or not a valid GeoJSON Polygon or MultiPolygon Feature, or
`nodes.mark_foreign: true` with no border source at all.
- `log.level` or `log.format` set to anything other than the listed values.
@@ -135,9 +136,8 @@ If you use the YAML setting instead, restarting Beacon is enough. Prefer the env
setting when using [backups](backup-export.md): exports refuse a nonempty
`meshmapper.api_key` in the saved YAML so the key cannot enter a download.
Beacon sends `X-API-Key` to `get_zones.php`, `get_geojson.php`, `get_scopes.php`, and
`get_channels.php`. Its shared client supports the same header for `get_repeaters.php`,
although Beacon does not currently fetch repeaters. Requests use trusted HTTPS MeshMapper
Beacon sends `X-API-Key` to `get_zones.php`, `get_geojson.php`, `get_scopes.php`,
`get_channels.php`, and `get_repeaters.php`. Requests use trusted HTTPS MeshMapper
endpoints and do not follow redirects. `get_zones.php` still needs its `country` parameter;
a key covering multiple regions does not change the request shape or remove rate limits.
IP exemptions are not authentication.
+2 -2
View File
@@ -60,7 +60,7 @@ Beacon refuses to run with a setting it cannot honour. The message names the key
| `scope "x" region "y" is not a configured region` | Use a slug that appears under `regions:`. |
| `netip.ParsePrefix("10.0.0.5"): no '/'` | Write `10.0.0.5/32`, not `10.0.0.5`. An empty entry fails with `server.trusted_proxies[0] must be a valid CIDR` instead. |
| `packets.retention must be at least 24h` | Raise it. Same for `analytics.rollup_retention`. |
| `meshmapper.scopes.refresh_interval must be between 1h and 24h` | Set it inside that range. Zones and channels intervals are 24h to 168h. |
| `meshmapper.scopes.refresh_interval must be between 1h and 24h` | Set it inside that range. Repeaters is also 1h to 24h; zones and channels intervals are 24h to 168h. |
| `nodes.mark_foreign requires an iatas.*.borderFile or meshmapper.zones` | Add a border source or turn `mark_foreign` off. |
| `not a well-formed GeoJSON Feature`, `ring 0 is not closed`, `geometry must be Polygon or MultiPolygon` | The border file is invalid. It must be a single GeoJSON Feature with a closed Polygon or MultiPolygon in longitude, latitude order. |
| `log level must be debug, info, warn or error` | Check `log.level` and `LOG_LEVEL`. `log format must be text or json` is the same for format. |
@@ -96,7 +96,7 @@ the stored messages for the new key and logs
## MeshMapper imports are unconfigured or stale
Read `docker compose logs app` for `component=meshmapper`, `meshmapper.zones`,
`meshmapper.scopes`, or `meshmapper.channels`. Refresh records include `last_error`,
`meshmapper.scopes`, `meshmapper.channels`, or `meshmapper.repeaters`. Refresh records include `last_error`,
`next_attempt`, and, for regional imports, `checked_at`.
| Message | Fix |