Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 87 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,89 @@
# Elevation Data Configuration
#
# Option 1: Use public OpenTopoData (default, 1000 requests/day)
# Just leave these commented out or blank
# meshRF configuration
#
# Option 2: Use a custom OpenTopoData instance (self-hosted or paid)
# ELEVATION_API_URL=http://your-opentopodata-instance:5000
# ELEVATION_DATASET=srtm30m
# Copy to `.env` in the project root -- docker compose reads it automatically
# for both docker-compose.yml (production) and docker-compose.dev.yml (dev).
# Every setting below is optional; the defaults shown are what you get if the
# variable is unset.
#
# Available datasets on public API: srtm30m, srtm90m, aster30m, etopo1, ned10m
# See: https://www.opentopodata.org/datasets/
# cp .env.example .env
#
# `.env` is gitignored and dockerignored, so it never lands in a commit or an
# image layer.

# =============================================================================
# Map Basemaps (CARTO)
# =============================================================================
#
# CARTO began requiring an API key for its raster basemaps in August 2026.
# Without one, the `dark`, `dark_green` and `light` styles still load but are
# stamped with an "API KEY REQUIRED" watermark. The `topo`, `topo_dark` and
# `satellite` styles come from Esri and need no key.
#
# Get a free key (5M tile requests/month, no account needed):
# https://carto.com/basemaps/apikey/
#
# The key is used server-side only. Nginx (production) and the Vite dev server
# both append it to tile requests as they pass through, so it is never written
# into the JavaScript bundle, never appears in env-config.js, and never shows
# up in the browser's network tab. Do NOT rename this to VITE_CARTO_API_KEY --
# a VITE_ prefix would inline it into the client bundle and publish it to every
# visitor.
#
# CARTO_API_KEY=

# =============================================================================
# Frontend Defaults
# =============================================================================
#
# In production these are applied when the container starts, so changing them
# needs only a `docker compose up -d`, not an image rebuild.

# Initial map center and zoom. Default: Portland, OR.
# MAP_LAT=45.5152
# MAP_LNG=-122.6784
# MAP_ZOOM=13

# Initial map theme.
# Options: dark, dark_green, light, topo, topo_dark, satellite
# DEFAULT_MAP_STYLE=dark_green

# Measurement system. Options: imperial, metric
# DEFAULT_UNITS=imperial

# =============================================================================
# Elevation Data (rf-engine)
# =============================================================================
#
# Option 1: Use the bundled self-hosted OpenTopoData container (default).
# You supply the terrain files -- see OPENTOPO_GUIDE.md for downloads.
#
# Option 2: Point at a different OpenTopoData instance (public or paid).
# The public API is capped at 1000 requests/day.
#
# ELEVATION_API_URL=http://opentopodata:5000

# Dataset served by that instance. Must match a dataset configured in
# data/opentopodata/config.yaml.
# Common choices: ned10m (high-res, US only), srtm30m (global), srtm90m,
# aster30m, etopo1. See https://www.opentopodata.org/datasets/
# ELEVATION_DATASET=ned10m

# =============================================================================
# Redis (caching + Celery broker)
# =============================================================================
#
# Change this before exposing meshRF beyond localhost -- the default is a
# well-known placeholder shared by every install.
# REDIS_PASSWORD=changeme
# REDIS_HOST=redis
# REDIS_PORT=6379

# =============================================================================
# Development Only (docker-compose.dev.yml)
# =============================================================================
#
# Hostnames the Vite dev server will accept, for running behind a reverse proxy
# or tunnel. Comma-separated, or `true` to allow any host. This is a Vite dev
# server option and has no effect on the production image, which serves through
# Nginx.
# ALLOWED_HOSTS=meshrf.example.com,localhost
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.17.1] - 2026-09-13

### Added

- **CARTO Basemap API Key Support**: CARTO began requiring an API key for its raster basemaps in August 2026; without one the `dark`, `dark_green` and `light` styles render with an "API KEY REQUIRED" watermark. Set `CARTO_API_KEY` in `.env` (free key: <https://carto.com/basemaps/apikey/>). The key is applied **server-side only** — the browser requests tiles from a same-origin `/basemaps/...` path, and Nginx (production) or the Vite dev/preview server (development) appends the key on the way to CARTO. It is therefore absent from the JS bundle, from `env-config.js` and from anything visible in devtools. The variable is deliberately *not* `VITE_`-prefixed, since Vite inlines those into the client bundle.
- Nginx caches proxied tiles locally (30 days, 512 MB) so repeat views do not spend the account's monthly quota, and the proxy clears any client-supplied query string so a caller cannot substitute their own key. The location regex only accepts well-formed `{style}/{z}/{x}/{y}.png` paths, so it cannot be driven as a general-purpose open proxy.
- `nginx.conf` is now a template rendered by `docker-entrypoint.sh` at container start, so the key is supplied at deploy time rather than baked into the published image.
- `MAP_ZOOM` configures the initial zoom level, alongside the now-working `MAP_LAT` / `MAP_LNG`.
- `src/utils/runtimeConfig.js` centralizes runtime configuration lookups (`window._env_` → `import.meta.env.VITE_*` → default), with range validation for numeric settings and unit tests covering both layers.

### Fixed

- **Map center environment variables had no effect** ([#23](https://github.com/d3mocide/MeshRF/issues/23)): `MapContainer` hardcoded Portland, OR and never read `VITE_MAP_LAT` / `VITE_MAP_LNG`. Two separate faults were involved — the variables were unused in the source, and `VITE_`-prefixed variables are inlined by Vite at *build* time, so setting them in `docker-compose.yml` could never reach the prebuilt image regardless. The initial view now resolves through `runtimeConfig`, and `docker-entrypoint.sh` writes `MAP_LAT` / `MAP_LNG` / `MAP_ZOOM` into `env-config.js` at container start. `VITE_MAP_LAT` / `VITE_MAP_LNG` are still accepted as deprecated aliases. Invalid or out-of-range values now warn and fall back to the default instead of handing Leaflet a `NaN`.
- `public/env-config.js` no longer ships populated defaults. Because `window._env_` takes priority over `import.meta.env`, its baked-in values silently shadowed the `VITE_*` variables during `npm run dev` — part of why the map-center settings appeared to do nothing.
- `vite preview` had no proxy configuration, so a built app served through it lost both `/api` and basemap proxying. Both servers now share one proxy definition.
- `docker-entrypoint.sh` rendered `nginx.conf` with `envsubst`, which comes from gettext and is not guaranteed to be present in the nginx base image — a missing binary would crash-loop the container on every start. Rendering now uses `sed`, which is part of busybox, with the substitution escaped so an API key containing `&`, `|` or `\` still renders correctly.

### Changed

- **`.env.example` rewritten**. It previously documented only two elevation variables and omitted everything else the stack actually reads. It now covers the basemap key, frontend defaults, elevation, Redis and dev-only settings, and Compose substitutes from it (`${MAP_LAT:-45.5152}`), so one `.env` drives both the production and development stacks.
- `README.md` version corrected to match `package.json` (was pinned at v1.16.1), configuration table rebuilt — it listed a `dark_matter` style that does not exist and omitted `topo_dark`, `MAP_ZOOM`, `ELEVATION_*`, `REDIS_PASSWORD` and `ALLOWED_HOSTS` — and a Basemap API Key section added.
- `MAP_STYLES` moved out of the `MapContainer` render body; it was rebuilt on every render, and the repeated attribution strings are now shared constants.
- `ALLOWED_HOSTS` removed from `docker-compose.yml` and added to `docker-compose.dev.yml`. It is a Vite dev-server option and had no effect on the production image, which serves through Nginx.

### Removed

- `VITE_ELEVATION_DATASET` read from `src/utils/elevation.js`. The `/elevation-batch` endpoint ignores the `dataset` field in the request body — dataset selection is made server-side by the rf-engine's `ELEVATION_DATASET` — so the variable configured nothing.

### Documentation

- `Documentation/README.md` linked to `elevation-scan.md`, which has never existed; the tool is now Site Analysis. Added the missing Tool Interactions and PWA guide links, and `link-analyzer.md` to the README's documentation list.
- `interactions.md` had a duplicated step 3/4 from a copy-paste error, and still referred to the renamed "Elevation Scan" tool. Its closing tip recommended Hata for verifying links, which assumes flat terrain; it now points at Bullington/ITM.
- `hardware-settings.md` was missing the Lilygo T-Deck and Custom Device presets, misnamed "Station G2 (High Power)", and documented no cable types despite the cable loss calculator shipping six. Preset names and gains realigned with `src/data/presets.js`.
- `site-analyzer.md` Multi-Site section predated the Inter-Node Link Matrix, Mesh Topology, Marginal Coverage and per-node coverage colors that the README already advertised.
- `rf-simulator.md` did not mention that coverage is computed with WASM ITM, nor the Ground Type / Climate Zone / Reliability inputs. `link-analyzer.md` gained the Reliability parameter.

## [1.17.0] - 2026-08-06

### Added
Expand Down
6 changes: 4 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ FROM nginx:alpine
# Copy build artifacts to Nginx html directory
COPY --from=builder /app/dist /usr/share/nginx/html

# Copy custom Nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Copy custom Nginx config as a template. The entrypoint renders it to
# conf.d/default.conf so CARTO_API_KEY can be supplied at container start
# rather than baked into the published image.
COPY nginx.conf /etc/nginx/templates/default.conf.template

# Copy Entrypoint Script
COPY docker-entrypoint.sh /
Expand Down
9 changes: 7 additions & 2 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@ Welcome to the MeshRF Documentation site. MeshRF is a powerful web-based toolset
- [**Link Analyzer**](./link-analyzer.md) - Point-to-point link budget and Fresnel zone analysis.
- [**Viewshed**](./viewshed.md) - Optical line-of-sight analysis using terrain data.
- [**RF Simulator**](./rf-simulator.md) - Radio propagation heatmaps and coverage analysis.
- [**Elevation Scan**](./elevation-scan.md) - Rapid terrain analysis to find ideal transmitter locations.
- [**Site Analysis**](./site-analyzer.md) - Rapid terrain analysis to find ideal transmitter locations, plus multi-site mesh planning.
- [**Hardware Settings**](./hardware-settings.md) - Detailed guide on devices, antennas, and radio presets.
- [**Batch Processing**](./batch-processing.md) - Bulk analysis and mesh report generation via CSV.

## Guides

- [**Tool Interactions**](./interactions.md) - How the tools combine into a planning workflow.
- [**PWA Guide**](./pwa-guide.md) - Installing meshRF on desktop and mobile.

## Getting Started

1. **Select a Tool**: Use the toolbar at the top of the map to select your analysis mode.
Expand All @@ -22,7 +27,7 @@ Welcome to the MeshRF Documentation site. MeshRF is a powerful web-based toolset

## How it Works

MeshRF combines high-resolution terrain data (DEM) with specialized RF propagation models (Free Space Path Loss, Okumura-Hata) to provide accurate predictions for wireless network performance.
MeshRF combines high-resolution terrain data (DEM) with specialized RF propagation models Free Space Path Loss, Okumura-Hata / COST 231, Bullington diffraction, and ITM (Longley-Rice) — to provide accurate predictions for wireless network performance.

---

Expand Down
35 changes: 25 additions & 10 deletions Documentation/hardware-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,42 @@ MeshRF allows you to configure specific hardware parameters to accurately simula

Selecting a device preset automatically configures the **Max TX Power** and **Internal Cable Loss**.

| Device | Max TX Power | Default Loss |
| --------------------------- | ------------ | ------------ |
| **Heltec V3** | 22 dBm | 1.5 dB |
| **Heltec V4 (High Power)** | 28 dBm | 1.5 dB |
| **Seeed Studio Xiao** | 22 dBm | 2.0 dB |
| **RAK WisBlock 4631** | 22 dBm | 0.5 dB |
| **Station G2 (High Power)** | 37 dBm (5W) | 0.5 dB |
| Device | Max TX Power | Default Loss |
| ------------------------------- | ------------ | ------------ |
| **Heltec V3** | 22 dBm | 1.5 dB |
| **Heltec V4 (High Power)** | 28 dBm | 1.5 dB |
| **Seeed Studio Xiao (SX1262)** | 22 dBm | 2.0 dB |
| **Lilygo T-Deck** | 22 dBm | 2.0 dB |
| **RAK WisBlock 4631** | 22 dBm | 0.5 dB |
| **Station G2** | 37 dBm (5W) | 0.5 dB |
| **Custom Device** | 37 dBm | 0.0 dB |

## 2. Antenna Types

The antenna type determines the gain (dBi) added to your signal.

- **Stubby (2.15 dBi)**: Standard small antenna included with most modules.
- **Stock / Stubby (2.15 dBi)**: Standard small antenna included with most modules.
- **Standard Dipole (3.0 dBi)**: Common half-wave dipole.
- **Fiberglass Omni (5.8 - 8.0 dBi)**: High-gain base station antennas for broad coverage.
- **Fiberglass Omni — Medium (5.8 dBi) / High (8.0 dBi)**: High-gain base station antennas for broad coverage.
- **Yagi (11.0 dBi)**: Directional antenna for long-range point-to-point links.
- **Custom**: Manually enter any gain value.

### Cable Types

The **Cable Loss Calculator** derives feedline loss from cable type and run length:

| Cable | Loss per meter |
| ----------------- | -------------- |
| **1/2" Heliax** | 0.038 dB |
| **LMR-400** | 0.128 dB |
| **LMR-240** | 0.249 dB |
| **RG-8X** | 0.262 dB |
| **RG-58** | 0.500 dB |
| **None / Direct** | 0.000 dB |

## 3. Radio Configuration (LoRa)

For the **RF Simulator** and **Link Analyzer**, these parameters define the signal's robustnes:
For the **RF Simulator** and **Link Analyzer**, these parameters define the signal's robustness:

- **Frequency (MHz)**: Higher frequencies (e.g., 915MHz) suffer more path loss than lower ones (e.g., 433MHz).
- **Bandwidth (BW)**: Narrower bandwidths increase sensitivity but decrease data rate.
Expand Down
9 changes: 4 additions & 5 deletions Documentation/interactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ MeshRF is most powerful when its tools are used in combination. This guide expla

A typical planning cycle often looks like this:

1. **Elevation Scan**: Start by scanning a wide area to find the highest potential site.
1. **Site Analysis**: Start by scanning a wide area to find the highest potential site.
2. **Viewshed**: Place an observer on the #1 ranked spot to verify visual coverage of your target area.
3. **RF Simulator**: Switch to the simulator to see how signal strength behaves with realistic hardware settings from that same spot.
4. **RF Simulator**: Switch to the simulator to see how signal strength behaves with realistic hardware settings from that same spot.
5. **Link Analyzer**: Finally, draw a point-to-point link between your new site and an existing node to verify the backbone connection.
4. **Link Analyzer**: Finally, draw a point-to-point link between your new site and an existing node to verify the backbone connection.

## Navigation & Controls

Expand All @@ -35,5 +34,5 @@ Changing the **Transmitter Height** in the Global Parameters sidebar will instan

## Tips for Success

- Use the **Topo Map** style when using the **Elevation Scan** to better understand the land features being analyzed.
- Always verify high-margin links with the **Realistic (Hata)** propagation model before finalizing a site.
- Use the **Topo Map** style when running **Site Analysis** to better understand the land features being analyzed.
- Always verify high-margin links with a terrain-aware model (**Bullington** or **ITM**) before finalizing a site. The Hata family assumes flat terrain.
1 change: 1 addition & 0 deletions Documentation/link-analyzer.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The **Link Analyzer** is designed for detailed point-to-point analysis between t
| **Antenna Height** | Increases clearance and reduces path loss. |
| **Frequency** | Higher frequencies have higher path loss and smaller Fresnel zones. |
| **Environment** | Urban vs. Rural affects the path loss calculation in Realistic mode. |
| **Reliability** | ITM only. Best Case (10%) / Typical (50%) / Reliable (90%) statistical confidence. Higher confidence predicts more path loss. |

> [!TIP]
> Use the **Lock** button to freeze a link and adjust transmitter parameters without losing your placement.
Expand Down
6 changes: 6 additions & 0 deletions Documentation/rf-simulator.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

The **RF Simulator** provides a radio propagation heatmap from a transmitter. Unlike the optical Viewshed, it accounts for frequency-specific attenuation and signal quality metrics.

Coverage is computed with the **ITM (Longley-Rice)** model running as a WASM
module in the browser, so it is terrain-aware and needs no backend round-trip
once the module has loaded.

## Features

- **SNR Heatmap**: Color-coded visualization of signal quality (SNR) across the area.
- **Threshold Awareness**: Fades out signals that fall below the configured receiver sensitivity.
- **Multi-Parameter Support**: Factors in Frequency, TX Power, Antenna Gain, and Spreading Factor.
- **Environment-Aware**: Honours the **Ground Type** (permittivity/conductivity) and **Climate Zone** set in the Environment sidebar.
- **Reliability Modes**: The **Reliability** control selects ITM's statistical confidence — Best Case (10%), Typical (50%, default) or Reliable (90%). Planning at *Reliable* shows the coverage you can count on in poor conditions rather than on a median day.

## How to Use

Expand Down
Loading
Loading