diff --git a/adn-server.example.yaml b/adn-server.example.yaml index 1b90b7f..6cdc0fb 100644 --- a/adn-server.example.yaml +++ b/adn-server.example.yaml @@ -49,6 +49,10 @@ ALIASES: KEYS_FILE: keys.json # Systems: MASTER, PEER, OPENBRIDGE. Names match legacy [SYSTEM], [D-APRS], [ECHO], [OBP-*]. +# +# SYSTEM + GENERATOR>1 expands to SYSTEM-0..SYSTEM-(GENERATOR-1), each with UDP PORT+n +# (e.g. PORT 56400 + GENERATOR 102 → listeners 56400–56501). Hotspot proxy must use the same +# PROXY.PORT and PROXY.GENERATOR in adn-monitor/proxy/adn-proxy.example.yaml. SYSTEMS: SYSTEM: MODE: MASTER diff --git a/docs/en/README.md b/docs/en/README.md index 3d352d8..f461e19 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -47,7 +47,7 @@ Dashboard, WebSocket live view, optional **PHP API**, **MySQL** self-service, an | I want to… | Start here | |------------|------------| -| `adn-mon.yaml` and layout | [Monitor configuration](monitor/configuration.md) | +| `adn-monitor.yaml`, `adn-proxy.yaml`, layout | [Monitor configuration](monitor/configuration.md), [Hotspot proxy](monitor/hotspot-proxy.md) | | Hotspot proxy (UDP, `PROXY`, peer port range) | [Hotspot proxy](monitor/hotspot-proxy.md) | | Self-service | [Self-service](monitor/self-service.md) | | How it connects to the server | [Monitoring and reports](server/user-guide/monitoring.md) | diff --git a/docs/en/monitor/architecture.md b/docs/en/monitor/architecture.md index 022141f..886fa49 100644 --- a/docs/en/monitor/architecture.md +++ b/docs/en/monitor/architecture.md @@ -21,7 +21,7 @@ Same opcodes as documented for the server: **CONFIG_SND**, **BRIDGE_SND**, **BRD ## PHP backend - **Slim 4** front controller: `backend/public/index.php`. -- Loads **`adn-mon.yaml`** via **`ADN_CONFIG_PATH`** (same as monitor). +- Loads **`adn-monitor.yaml`** via **`ADN_CONFIG_PATH`** (same as monitor). - **`/api/config/dashboard`** — title, language, feature flags (`selfService`, `showConsole`, …) from **`DASHBOARD`**. - **`/api/auth/*`** — session cookie auth when **SELF_SERVICE** DB is available. - **`/api/self-service/*`** — device options (see [Self-service](self-service.md)). @@ -35,18 +35,18 @@ Same opcodes as documented for the server: **CONFIG_SND**, **BRIDGE_SND**, **BRD ## Hotspot proxy - Entry: `proxy/proxy.py`; package `src/adn_proxy/` (domain / application / infrastructure). -- Reads **`PROXY`** and **`SELF_SERVICE`** from the same YAML. -- For each hotspot client, allocates a port in **`DESTPORT_START`…`DEST_PORT_END`** and forwards UDP to **`MASTER`**. +- Reads **`PROXY`** and **`SELF_SERVICE`** from **`adn-proxy.yaml`** by default (or from the same file as the monitor when **`ADN_CONFIG_PATH`** is used without **`ADN_PROXY_CONFIG_PATH`** — see [Hotspot proxy](hotspot-proxy.md#configuration-file)). +- For each hotspot client, allocates a UDP port in **`PORT`…`PORT+GENERATOR-1`** (YAML **`PORT`** + **`GENERATOR`**, matching **`adn-server`**) and forwards to **`MASTER`**. - When **self-service** updates **`Clients.options`** and sets **`modified=1`**, the proxy sends **RPTO** to the **master** on a timer (~10 s). The **peer server** then applies options to the hotspot path (see [Self-service](self-service.md)). -**Why it is not part of the peer server binary:** it shares **`adn-mon.yaml`**, MySQL self-service, and deployment with the monitor stack — see [Why it ships with the monitor](hotspot-proxy.md#why-it-ships-with-the-monitor-not-inside-the-peer-server). +**Why it is not part of the peer server binary:** it shares deployment, **`SELF_SERVICE`** MySQL, and packaging with the monitor stack — see [Why it ships with the monitor](hotspot-proxy.md#why-it-ships-with-the-monitor-not-inside-the-peer-server). **Details:** [Hotspot proxy](hotspot-proxy.md) (config keys, peer server port range, startup). ## Typical deployment topology ```text -[Hotspots] --UDP--> [Proxy :LISTEN_PORT] --UDP--> [Peer server :DESTPORT range] +[Hotspots] --UDP--> [Proxy :LISTEN_PORT] --UDP--> [Peer server :PORT..PORT+GENERATOR-1] | v MySQL (Clients) diff --git a/docs/en/monitor/configuration.md b/docs/en/monitor/configuration.md index 4c5bf27..5a13d9c 100644 --- a/docs/en/monitor/configuration.md +++ b/docs/en/monitor/configuration.md @@ -1,6 +1,10 @@ -# Configuration (`adn-mon.yaml`) +# Configuration (`adn-monitor.yaml`) -All components read the **same** YAML (default path often `monitor/adn-mon.yaml`; override with **`ADN_CONFIG_PATH`**). The example shipped in the **adn-monitor** repo is the authoritative template; keys below match `monitor/adn-mon.yaml` and `monitor/src/adn_monitor/infrastructure/config_loader.py` (internal names may differ). +This document describes **`adn-monitor.yaml`**, used by the **Python monitor** (`monitor/monitor.py`) and the **PHP backend** (`backend/public/index.php`). Default path is usually **`monitor/adn-monitor.yaml`** (override with **`ADN_CONFIG_PATH`**). + +The **hotspot proxy** loads a **separate** file by default — **`proxy/adn-proxy.yaml`** — see [Hotspot proxy](hotspot-proxy.md). **`SELF_SERVICE`** (MySQL / PBKDF2) must stay **identical** between the two YAML files when both are used. + +The example shipped in the **adn-monitor** repo (`monitor/adn-monitor.yaml.example`) is the template for the monitor; keys below match that file and `monitor/src/adn_monitor/infrastructure/config_loader.py` (internal names may differ). --- @@ -19,7 +23,7 @@ All components read the **same** YAML (default path often `monitor/adn-mon.yaml` --- -## `ADN_CONNECTION` +## `ADN_CONNECTION` {#adn_connection} Must match the **ADN DMR Peer Server** reporting configuration. @@ -27,6 +31,7 @@ Must match the **ADN DMR Peer Server** reporting configuration. |-----|---------| | **ADN_IP** | Host/IP where the **peer server’s report TCP listener** is bound (from the monitor’s network view). | | **ADN_PORT** | TCP port — must equal **`REPORTS.REPORT_PORT`** on the server and be reachable. | +| **HELLO_TIMEOUT_MS** | After TCP connect, how long to wait for opcode **`0xFF` HELLO** (JSON) from **new-adn-server**. If nothing arrives in time, the monitor treats the peer as **legacy** (pickled CONFIG/BRIDGE only). Default **1500** ms. See [Monitoring and reports](../server/user-guide/monitoring.md). | --- @@ -45,13 +50,16 @@ If the PHP backend cannot connect, **auth** and **self-service** API routes are ## `PROXY` -Hotspot **UDP proxy** — full guide: [Hotspot proxy](hotspot-proxy.md). Summary: forwards each client to **`MASTER:DESTPORT_START`…`DEST_PORT_END`**; the peer server must **listen** on that IP and port range (see also [Architecture](architecture.md)). +Hotspot **UDP proxy** — full guide: [Hotspot proxy](hotspot-proxy.md). In current layouts, these keys live in **`proxy/adn-proxy.yaml`**, not in `adn-monitor.yaml`. **Legacy:** a single file can still contain **PROXY** if the proxy is started with **`ADN_CONFIG_PATH`** pointing at that file (see resolution order in [Hotspot proxy](hotspot-proxy.md#configuration-file)). + +Summary: **`PORT`** + **`GENERATOR`** must match **`SYSTEM.PORT`** + **`SYSTEM.GENERATOR`** in `adn-server`; each client is forwarded to **`MASTER`** at one UDP port in **`PORT`…`PORT+GENERATOR-1`** (see also [Architecture](architecture.md)). | Key | Meaning | |-----|---------| | **MASTER** | Peer server host (IP or DNS; resolved at proxy startup). | | **LISTEN_PORT** / **LISTEN_IP** | Where the proxy accepts hotspot UDP (empty IP often means all interfaces). | -| **DESTPORT_START** / **DEST_PORT_END** | One port per proxied client toward **`MASTER`**. | +| **PORT** / **DESTPORT_START** | Base UDP port on **`MASTER`** (same as server SYSTEM **PORT**). | +| **GENERATOR** | Count of consecutive UDP ports on **`MASTER`** (same integer as server SYSTEM **GENERATOR**). | | **TIMEOUT**, **STATS**, **DEBUG**, **CLIENT_INFO** | Behaviour and logging. | | **BLACK_LIST** / **IP_BLACK_LIST** | Optional block lists. | @@ -74,10 +82,11 @@ Similar idea to the peer server: download **peer / subscriber / TGID** JSON and | Key | Meaning | |-----|---------| | **LOG_PATH** | Directory for log files. | -| **LOG_FILE** | Monitor log filename (e.g. `adn-mon.log`). | -| **PROXY_LOG_FILE** | Separate log name for the proxy (when run with proxy logging). | +| **LOG_FILE** | Monitor log filename (e.g. `adn-monitor.log`). | | **LOG_LEVEL** | e.g. `INFO`, `DEBUG`. | +The **hotspot proxy** log filename is set in **`proxy/adn-proxy.yaml`** under **LOGGER** as **`PROXY_LOG_FILE`** (see [Hotspot proxy](hotspot-proxy.md)). + --- ## `WEBSOCKET_SERVER` @@ -107,7 +116,8 @@ Similar idea to the peer server: download **peer / subscriber / TGID** JSON and ## Environment -- **`ADN_CONFIG_PATH`**: Absolute path to `adn-mon.yaml` for monitor, backend, and proxy. +- **`ADN_CONFIG_PATH`**: Absolute path to **`adn-monitor.yaml`** for the **monitor** and **PHP backend**. +- **`ADN_PROXY_CONFIG_PATH`** (optional): Absolute path to **`adn-proxy.yaml`** for the hotspot proxy. If unset, the proxy falls back to **`ADN_CONFIG_PATH`** (legacy combined file), then to **`proxy/adn-proxy.yaml`** by default — details in [Hotspot proxy](hotspot-proxy.md#configuration-file). - Backend may use **`API_BASE_PATH`** if the API is mounted under a prefix. --- diff --git a/docs/en/monitor/hotspot-proxy.md b/docs/en/monitor/hotspot-proxy.md index c61b6e0..02ed9a5 100644 --- a/docs/en/monitor/hotspot-proxy.md +++ b/docs/en/monitor/hotspot-proxy.md @@ -8,7 +8,7 @@ Source layout: `proxy/proxy.py`, package `proxy/src/adn_proxy/` (clean architect There is no single mandatory layout for every deployment, but **today the proxy lives in the adn-monitor repo** on purpose: -- **Same config and ops** as the dashboard stack: **`adn-mon.yaml`**, **`ADN_CONFIG_PATH`**, and usually the same host as **PHP** and **MySQL**. +- **Same deployment** as the dashboard stack: **`ADN_CONFIG_PATH`** / **`ADN_PROXY_CONFIG_PATH`**, **`adn-monitor.yaml`** + **`adn-proxy.yaml`**, and usually the same host as **PHP** and **MySQL**. - **Self-service** ( **`Clients`**, RPTO, **`modified`**) is built around that ecosystem; the peer server binary does not own that database or the **`PROXY`** block. - **Role split:** the **ADN DMR Peer Server** is the **radio core** (HBP/OpenBridge, bridges, voice, TCP reports). The hotspot proxy is an **optional UDP front** toward a MASTER that already listens on a port **range** — useful when many hotspots share one public address. @@ -16,34 +16,40 @@ There is no single mandatory layout for every deployment, but **today the proxy --- -## Configuration file (same as monitor) +## Configuration file {#configuration-file} -The proxy does **not** use `adn-server.yaml`. It reads the **monitor** YAML: +The proxy does **not** use `adn-server.yaml`. It reads YAML that contains **`PROXY`**, **`SELF_SERVICE`**, and **`LOGGER`** (proxy log). -| Source | Purpose | -|--------|---------| -| **`ADN_CONFIG_PATH`** | Environment variable: absolute path to **`adn-mon.yaml`** (shared with **monitor**, **PHP backend**, optional **`.env`** in repo root). | -| **`python proxy/proxy.py --config /path/to/adn-mon.yaml`** | Overrides the path for this process only. | -| **Default** (if unset) | `../monitor/adn-mon.yaml` relative to the `proxy/` directory when run from the adn-monitor tree. | +### Resolution order -Sections used: +| Priority | Source | Purpose | +|----------|--------|---------| +| 1 | **`python proxy/proxy.py --config /path/to/file.yaml`** | Overrides config path for this process only. | +| 2 | **`ADN_PROXY_CONFIG_PATH`** | Optional env: absolute path to **`adn-proxy.yaml`** (typical dedicated proxy config). | +| 3 | **`ADN_CONFIG_PATH`** | Legacy: absolute path to a **combined** file (e.g. **`adn-monitor.yaml`** with **PROXY** embedded — same as monitor/backend). | +| 4 | **Default** | **`proxy/adn-proxy.yaml`** next to `proxy/proxy.py` when neither env var is set. | + +Copy **`proxy/adn-proxy.example.yaml`** to **`proxy/adn-proxy.yaml`** and edit. **`SELF_SERVICE`** must match **`monitor/adn-monitor.yaml`** (same DB credentials and PBKDF2 parameters). + +Sections read from whichever file is chosen: - **`PROXY`** — listen address, master host, destination port **range**, timeouts, debug, block lists. - **`SELF_SERVICE`** — MySQL and **`USE_SELFSERVICE`** (for **`Clients`** table, RPTO / options). -- **`LOGGER`** — **`LOG_PATH`** and **`PROXY_LOG_FILE`** (proxy log is separate from **`LOG_FILE`** used by `monitor.py`). +- **`LOGGER`** — **`LOG_PATH`** and **`PROXY_LOG_FILE`** (separate from **`LOG_FILE`** in `adn-monitor.yaml` for `monitor.py`). Optional **environment** overrides (see `proxy/README.md` in the repo): e.g. **`ADN_PROXY_DEBUG`**, **`ADN_PROXY_LISTENPORT`**. --- -## `PROXY` keys (`adn-mon.yaml`) +## `PROXY` keys (in `adn-proxy.yaml`, or legacy combined YAML) | Key | Role | |-----|------| | **MASTER** | IP or **hostname** of the **ADN DMR Peer Server** host. Resolved to an IPv4 address at startup (Twisted requires an IP for `write()`). | | **LISTEN_PORT** | UDP port where **hotspots** connect **to the proxy** (the address users configure on the hotspot). | | **LISTEN_IP** | Empty often means all interfaces; otherwise bind to this address. | -| **DESTPORT_START** / **DEST_PORT_END** | Inclusive range of UDP ports on **`MASTER`** used **one per proxied hotspot** (sequential allocation inside the proxy). | +| **PORT** / **DESTPORT_START** | Base UDP port on **`MASTER`** (alias **DESTPORT_START**); must match **`SYSTEM.PORT`** in `adn-server`. | +| **GENERATOR** | Same integer as **`SYSTEM.GENERATOR`**; UDP ports **`PORT`…`PORT+GENERATOR-1`** on **`MASTER`** (one per proxied hotspot session). | | **TIMEOUT** | Idle / session timeout (seconds). | | **STATS** | Extra statistics logging. | | **DEBUG** | Verbose packet logging (or use **`ADN_PROXY_DEBUG=1`**). | @@ -56,12 +62,12 @@ Internal config keys (after load) use mixed-case names (`Master`, `ListenPort`, ## Peer server (`adn-server.yaml`) must cover the port range -The proxy forwards traffic to **`MASTER:DESTPORT`** for each client, where **DESTPORT** is chosen inside **[DESTPORT_START, DEST_PORT_END]**. +The proxy forwards traffic to **`MASTER:assigned_port`** for each client, where **assigned_port** is picked from **`PORT`…`PORT+GENERATOR-1`** (same **PORT**/**GENERATOR** semantics as [Server configuration](../server/user-guide/configuration.md)). -The **ADN DMR Peer Server** must therefore **listen on UDP** on **that host** for **every port** in the range that you intend to use (one **MASTER** listener per port, or equivalent). +The **ADN DMR Peer Server** must **listen on UDP** on **that host** for **every port** in that range (usually via **`GENERATOR`** on one SYSTEM block). -- A **single** `MODE: MASTER` with **one** `PORT` is **not** enough for multiple proxy clients if they map to different **DESTPORT** values — you need **multiple listeners** on the range. -- Typical approaches: **`GENERATOR`** on a MASTER system (splits into `NAME-0`, `NAME-1`, … with consecutive **PORT** values — see [Server configuration](../server/user-guide/configuration.md)), and/or multiple **`SYSTEMS`** entries, aligned with **`DESTPORT_START`…`DEST_PORT_END`** in **`PROXY`**. +- Align **`PROXY.PORT`** and **`PROXY.GENERATOR`** with **`SYSTEM.PORT`** and **`SYSTEM.GENERATOR`** in **`adn-server.yaml`**. +- Typical setup: one **`MODE: MASTER`** entry with **`GENERATOR`** expanding to `SYSTEM-0`…`SYSTEM-(N-1)` on consecutive UDP ports — see [Server configuration](../server/user-guide/configuration.md). If the server only listens on e.g. **56400** but the proxy sends to **56401**, that client will not register. @@ -69,18 +75,27 @@ If the server only listens on e.g. **56400** but the proxy sends to **56401**, t ## How the process starts -1. Resolve config path (`ADN_CONFIG_PATH`, `--config`, or default). +1. Resolve config path (`--config`, **`ADN_PROXY_CONFIG_PATH`**, **`ADN_CONFIG_PATH`**, or default **`proxy/adn-proxy.yaml`**). 2. **`load_config()`** parses YAML → **`PROXY`**, **`SELF_SERVICE`**, **`LOG`**. 3. Optional **MySQL** pool if self-service / DB features are enabled. 4. Twisted **reactor** runs UDP **ProxyProtocol** on **`LISTEN_IP:LISTEN_PORT`**, forwarding to **`MASTER:assigned_dest_port`**. -Run (from adn-monitor root, with env set): +Run (from adn-monitor root): ```bash -export ADN_CONFIG_PATH=/opt/adn-monitor/monitor/adn-mon.yaml +# Dedicated proxy YAML (recommended) +export ADN_PROXY_CONFIG_PATH=/opt/adn-monitor/proxy/adn-proxy.yaml +python proxy/proxy.py + +# Or rely on default proxy/adn-proxy.yaml after copying from adn-proxy.example.yaml python proxy/proxy.py -# or -python proxy/proxy.py --config /path/to/adn-mon.yaml + +# Legacy: single combined monitor YAML +export ADN_CONFIG_PATH=/opt/adn-monitor/monitor/adn-monitor.yaml +python proxy/proxy.py + +# Or explicit path for one run +python proxy/proxy.py --config /opt/adn-monitor/proxy/adn-proxy.yaml ``` Use **systemd** or another supervisor to run alongside **`monitor.py`** and the **PHP** stack. @@ -103,12 +118,12 @@ Details: [Self-service](self-service.md) and the **adn-monitor** `proxy/README.m ## Monitor visibility -Hotspots appear on the dashboard only if the **peer server** sends **TCP reports** to the same host/port as **`ADN_CONNECTION`** in **`adn-mon.yaml`**. Align **`REPORTS`** on the server with **`ADN_IP` / `ADN_PORT`**. See [Monitoring and reports](../server/user-guide/monitoring.md). +Hotspots appear on the dashboard only if the **peer server** sends **TCP reports** to the same host/port as **`ADN_CONNECTION`** in **`adn-monitor.yaml`**. Align **`REPORTS`** on the server with **`ADN_IP` / `ADN_PORT`**. See [Monitoring and reports](../server/user-guide/monitoring.md). --- ## See also -- [Monitor configuration](configuration.md) — full **`adn-mon.yaml`** reference (PROXY section summary). +- [Monitor configuration](configuration.md) — **`adn-monitor.yaml`** (dashboard, reports, MySQL for backend/monitor); **`PROXY`** detail above. - [Architecture](architecture.md) — where the proxy sits in the stack. - [Self-service](self-service.md) — DB, **`modified`**, RPTO timing. diff --git a/docs/en/monitor/index.md b/docs/en/monitor/index.md index bf81c3f..9e46de5 100644 --- a/docs/en/monitor/index.md +++ b/docs/en/monitor/index.md @@ -9,32 +9,31 @@ This chapter documents the **adn-monitor** stack at the same level of detail as | Part | Role | |------|------| | **`monitor/monitor.py`** | Python (Twisted): connects to the peer server’s **report TCP** port, decodes netstring payloads (`CONFIG_SND`, `BRIDGE_SND`, `BRDG_EVENT`), maintains **CTABLE** / **BTABLE**, writes **Last Heard** / TG stats to **MySQL** when configured, serves **WebSocket** JSON to the dashboard. | -| **`backend/`** | PHP **Slim** app: `/api/config/dashboard`, auth, optional **self-service** APIs, alias proxies. Reads the **same** `adn-mon.yaml` via **`ADN_CONFIG_PATH`**. | +| **`backend/`** | PHP **Slim** app: `/api/config/dashboard`, auth, optional **self-service** APIs, alias proxies. Reads **`adn-monitor.yaml`** via **`ADN_CONFIG_PATH`**. | | **`frontend/`** | React (Vite): dashboard UI; consumes backend API + WebSocket. | -| **`proxy/`** | Python (Twisted): UDP **hotspot proxy**; forwards Homebrew between hotspots and the peer server; reads **`Clients`** in MySQL for **RPTO** options (self-service). | +| **`proxy/`** | Python (Twisted): UDP **hotspot proxy**; forwards Homebrew between hotspots and the peer server; reads **`Clients`** in MySQL for **RPTO** options (self-service). Loads **`adn-proxy.yaml`** by default (see [Hotspot proxy](hotspot-proxy.md)). | -## Single configuration file +## Configuration files -**`adn-mon.yaml`** (path often set with **`ADN_CONFIG_PATH`** in `.env`) is shared by: +| File | Used by | Typical env | +|------|---------|-------------| +| **`monitor/adn-monitor.yaml`** | **`monitor.py`**, **PHP backend** | **`ADN_CONFIG_PATH`** | +| **`proxy/adn-proxy.yaml`** | **`proxy/proxy.py`** | **`ADN_PROXY_CONFIG_PATH`** (optional; defaults and legacy fallback in [Hotspot proxy](hotspot-proxy.md#configuration-file)) | -- Python monitor (`monitor.py`) -- PHP backend (`backend/public/index.php`) -- Hotspot proxy (`proxy/proxy.py`) - -So **one** YAML drives reporting addresses, dashboard strings, WebSocket port, **SELF_SERVICE** DB credentials, and **PROXY** listen/range settings. +**`SELF_SERVICE`** (MySQL / PBKDF2) must **match** between both YAML files when you split config. **`ADN_CONNECTION`**, dashboard, WebSocket, and aliases live in **`adn-monitor.yaml`**; **`PROXY`** listen/master/range settings live in **`adn-proxy.yaml`** unless you use a **legacy** single file via **`ADN_CONFIG_PATH`** for the proxy. ## Link to the peer server -| Server (`adn-server.yaml`) | Monitor (`adn-mon.yaml`) | +| Server (`adn-server.yaml`) | Monitor (`adn-monitor.yaml`) | |----------------------------|---------------------------| | **`REPORTS.REPORT_CLIENTS`** — list of IPs allowed to connect **to** the report listener, or the monitor host | **`ADN_CONNECTION.ADN_IP`** / **`ADN_PORT`** — where the **monitor connects** (must match the server’s report bind and port). | | **`REPORTS.REPORT_PORT`** — TCP port the **server listens on** for incoming report connections | Same port as **`ADN_PORT`**. | -See [Monitoring and reports](../server/user-guide/monitoring.md) for report opcodes and [Monitor configuration](configuration.md) for every `adn-mon.yaml` section. +See [Monitoring and reports](../server/user-guide/monitoring.md) for report opcodes and [Monitor configuration](configuration.md) for every `adn-monitor.yaml` section. ## See also - [Hotspot proxy](hotspot-proxy.md) — `PROXY`, peer server port range, how the process loads config and runs - [Architecture and deployment](architecture.md) -- [Configuration (`adn-mon.yaml`)](configuration.md) +- [Configuration (`adn-monitor.yaml`)](configuration.md) - [Self-service](self-service.md) diff --git a/docs/en/monitor/self-service.md b/docs/en/monitor/self-service.md index 1a7ffec..5c41609 100644 --- a/docs/en/monitor/self-service.md +++ b/docs/en/monitor/self-service.md @@ -8,7 +8,7 @@ It involves **four** pieces: **MySQL** (`Clients` table), **PHP API** (session + ## Prerequisites -1. **`SELF_SERVICE`** block in **`adn-mon.yaml`** with valid **MySQL** credentials and **PBKDF2** parameters matching your password tooling (same salt/iterations as **`hotspot_proxy_self_service.py`** when used). +1. **`SELF_SERVICE`** block in **`adn-monitor.yaml`** with valid **MySQL** credentials and **PBKDF2** parameters matching your password tooling (same salt/iterations as **`hotspot_proxy_self_service.py`** when used). 2. **`DASHBOARD.SELF_SERVICE: true`** so the UI shows the **Self-service** menu entry (and the backend exposes `/api/self-service/*` when DB connects). 3. **`Clients`** table populated with rows: **`callsign`**, **`int_id`** (DMR ID), **`psswd`** (PBKDF2-SHA256 hex), **`options`** (semicolon-separated `KEY=value`), **`logged_in`**, **`host`**, **`modified`**, etc. (see adn-monitor DB schema / migration scripts in the repo). 4. Hotspot traffic should pass through the **proxy** if you rely on **`modified`** and **RPTO** push (see flow below). diff --git a/docs/en/server/contributing/translations.md b/docs/en/server/contributing/translations.md index 2ae11b9..51ba812 100644 --- a/docs/en/server/contributing/translations.md +++ b/docs/en/server/contributing/translations.md @@ -10,7 +10,7 @@ | Spanish | **`docs/es/`** | **`mkdocs.es.yml`** → **`site/es/`** | - **`docs/en/server/`** — ADN DMR Peer Server (user guide, protocols, development, contributing). -- **`docs/en/monitor/`** — ADN Monitor (dashboard, `adn-mon.yaml`, self-service). +- **`docs/en/monitor/`** — ADN Monitor (dashboard, `adn-monitor.yaml`, self-service). Spanish mirrors the same relative paths under **`docs/es/`**. diff --git a/docs/en/server/user-guide/attribution.md b/docs/en/server/user-guide/attribution.md index e3d3002..04e48a3 100644 --- a/docs/en/server/user-guide/attribution.md +++ b/docs/en/server/user-guide/attribution.md @@ -2,7 +2,7 @@ ## Credits and lineage -**ADN Systems DMR Peer Server** is derived from **FreeDMR**, reorganised with **clean architecture** (domain, application, infrastructure) and ADN-specific features: scheduled announcements, **TTS**, on-demand voice, **`adn-voice.yaml`** merge, TCP reporting to **ADN Monitor**, integration with **`adn-mon.yaml`**, self-service, hotspot proxy, and more. +**ADN Systems DMR Peer Server** is derived from **FreeDMR**, reorganised with **clean architecture** (domain, application, infrastructure) and ADN-specific features: scheduled announcements, **TTS**, on-demand voice, **`adn-voice.yaml`** merge, TCP reporting to **ADN Monitor**, integration with **`adn-monitor.yaml`**, self-service, hotspot proxy, and more. **[FreeDMR Peer Server](https://gitlab.hacknix.net/hacknix/FreeDMR)** is by **Simon Adlem, G7RZU** ([hacknix](https://gitlab.hacknix.net/hacknix/FreeDMR)). diff --git a/docs/en/server/user-guide/introduction.md b/docs/en/server/user-guide/introduction.md index 8e54c84..38e78c9 100644 --- a/docs/en/server/user-guide/introduction.md +++ b/docs/en/server/user-guide/introduction.md @@ -32,5 +32,5 @@ Routing, timers, OpenBridge loop control, and protocol handling are implemented - [Configuration](configuration.md) — files, `GLOBAL`, **MASTER** / **PEER** / **OPENBRIDGE**, ACLs, reports, aliases, voice merge. - [Bridges and talkgroups](bridges-and-talkgroups.md) — how `BRIDGES` works. - [Special numbers](special-numbers.md) — TG 4000, information services, echo. -- [ADN Monitor](../../monitor/index.md) — dashboard, `adn-mon.yaml`, self-service (separate repo, deployed with the server). +- [ADN Monitor](../../monitor/index.md) — dashboard, `adn-monitor.yaml`, self-service (separate repo, deployed with the server). - [Credits & license](attribution.md) — ADN → FreeDMR → hblink3, license. diff --git a/docs/en/server/user-guide/monitoring.md b/docs/en/server/user-guide/monitoring.md index b4a138c..545dfe4 100644 --- a/docs/en/server/user-guide/monitoring.md +++ b/docs/en/server/user-guide/monitoring.md @@ -4,13 +4,30 @@ When **`REPORTS`** is enabled in the server config, the **ADN DMR Peer Server** listens on TCP and **report clients** (typically **adn-monitor**) connect and receive: -- **CONFIG_SND** / **BRIDGE_SND** — pickled snapshots of systems and bridges. +- **HELLO** (opcode **`0xFF`**) — JSON sent **first** on each new TCP connection by **new-adn-server** (`adn-server`): `server` name, package **`version`**, **`protocol`** number, and **`features`** (e.g. `INGRESS`, `END_TX_FORWARD`, `PUSH_ON_CONNECT`). Lets the monitor tag the session as **v2** before any pickled payloads. +- **CONFIG_SND** / **BRIDGE_SND** — pickled snapshots of systems and bridges (sent immediately after HELLO on connect, and again on updates / request). - **BRDG_EVENT** — text events for calls (`GROUP VOICE`, `PRIVATE VOICE`, etc.). +Older stacks (**legacy** `adn-dmr-server`-style) may **omit** HELLO. **adn-monitor** waits up to **`ADN_CONNECTION.HELLO_TIMEOUT_MS`** (see [Monitor configuration](../../monitor/configuration.md#adn_connection)); if no HELLO arrives, it assumes **legacy** reporting. + The **monitor** decodes these messages, updates its **CTABLE** / **BTABLE**, and (when MySQL is configured) persists Last Heard / statistics. **Full stack:** [ADN Monitor overview](../../monitor/index.md) (Python monitor, WebSocket, PHP API, optional proxy and self-service). +### Report channel log lines (`adn-monitor` logger) + +Python uses the logger name **`adn-monitor`** (see **`LOGGER.LOG_FILE`** in `adn-monitor.yaml`). Typical **INFO** lines for the TCP report client: + +| Log prefix / text | Meaning | +|-------------------|---------| +| `(REPORT) Connection to report server established` | TCP session up; HELLO wait timer starts (**`HELLO_TIMEOUT_MS`**). | +| `(REPORT) stringReceived: HELLO opcode=ff …` | Raw HELLO frame seen on the wire. | +| `(REPORT) HELLO received: mode=v2 server=… version=… features=…` | HELLO JSON parsed; session treated as **v2** (**new-adn-server**). | +| `(REPORT) No HELLO in …s; assuming legacy adn-dmr-server …` | No **`0xFF`** before timeout — monitor keeps **legacy** mode (pickled CONFIG/BRIDGE only). Expected if the peer is classic **`adn-dmr-server`**. If you **know** the server is **new-adn-server** but still see this, check **`ADN_IP`** / **`ADN_PORT`**, **`REPORTS.REPORT_CLIENTS`**, firewalls, or raise **`HELLO_TIMEOUT_MS`** slightly on very slow links. | +| `(REPORT) CONFIG applied: …` / `(REPORT) BRIDGES applied: …` | Pickled snapshots applied to CTABLE/BTABLE. | + +At **WARNING**: invalid HELLO JSON (`(REPORT) HELLO payload not valid JSON`), or **`Invalid GLOBAL.TIMEZONE`** if **`GLOBAL.TIMEZONE`** in YAML is not a valid IANA name. + ## OpenBridge monitor semantics - **`GROUP VOICE,INGRESS,RX`** — first sight of a stream on an OpenBridge **leg** (debug; full visibility in logs). @@ -26,4 +43,4 @@ The dashboard shows **operational** state from **START** (canonical); the **Moni ## Self-service and hotspots -Operators editing **device options** from the dashboard use the **self-service** flow (MySQL **`Clients`**, proxy **RPTO**). That is documented under [Self-service](../../monitor/self-service.md); it is **not** part of the peer server binary alone. For **hotspot proxy** configuration (`PROXY` in `adn-mon.yaml`), how it binds to the peer server **UDP port range**, and how the process starts, see [Hotspot proxy](../../monitor/hotspot-proxy.md). +Operators editing **device options** from the dashboard use the **self-service** flow (MySQL **`Clients`**, proxy **RPTO**). That is documented under [Self-service](../../monitor/self-service.md); it is **not** part of the peer server binary alone. For **hotspot proxy** configuration (`PROXY` in **`adn-proxy.yaml`** by default), how it binds to the peer server **UDP port range**, and how the process starts, see [Hotspot proxy](../../monitor/hotspot-proxy.md). diff --git a/docs/es/README.md b/docs/es/README.md index 65e8de0..3d99388 100644 --- a/docs/es/README.md +++ b/docs/es/README.md @@ -46,7 +46,7 @@ Panel, **WebSocket** en vivo, **API PHP** opcional, **MySQL** self-service y **p | Quiero… | Empieza aquí | |---------|----------------| -| `adn-mon.yaml` y despliegue | [Configuración del monitor](monitor/configuration.md) | +| `adn-monitor.yaml`, `adn-proxy.yaml`, despliegue | [Configuración del monitor](monitor/configuration.md), [Proxy hotspot](monitor/hotspot-proxy.md) | | Proxy hotspot (UDP, `PROXY`, rango de puertos) | [Proxy hotspot](monitor/hotspot-proxy.md) | | Self-service | [Self-service](monitor/self-service.md) | | Cómo encaja con el servidor | [Monitor e informes](server/user-guide/monitoring.md) | diff --git a/docs/es/monitor/architecture.md b/docs/es/monitor/architecture.md index 456fb52..bed7ea4 100644 --- a/docs/es/monitor/architecture.md +++ b/docs/es/monitor/architecture.md @@ -21,7 +21,7 @@ Los mismos opcodes que en la documentación del servidor: **CONFIG_SND**, **BRID ## Backend PHP - **Slim 4** front controller: `backend/public/index.php`. -- Carga **`adn-mon.yaml`** vía **`ADN_CONFIG_PATH`** (igual que el monitor). +- Carga **`adn-monitor.yaml`** vía **`ADN_CONFIG_PATH`** (igual que el monitor). - **`/api/config/dashboard`** — título, idioma, flags (`selfService`, `showConsole`, …) desde **`DASHBOARD`**. - **`/api/auth/*`** — sesión por cookie cuando hay BD **SELF_SERVICE**. - **`/api/self-service/*`** — opciones de dispositivo (ver [Self-service](self-service.md)). @@ -35,18 +35,18 @@ Los mismos opcodes que en la documentación del servidor: **CONFIG_SND**, **BRID ## Proxy hotspot - Entrada: `proxy/proxy.py`; paquete `src/adn_proxy/` (dominio / aplicación / infraestructura). -- Lee **`PROXY`** y **`SELF_SERVICE`** del mismo YAML. -- Por cada cliente hotspot, asigna un puerto en **`DESTPORT_START`…`DEST_PORT_END`** y reenvía UDP a **`MASTER`**. +- Lee **`PROXY`** y **`SELF_SERVICE`** desde **`adn-proxy.yaml`** por defecto (o desde el mismo fichero que el monitor si se usa solo **`ADN_CONFIG_PATH`** sin **`ADN_PROXY_CONFIG_PATH`** — ver [Proxy hotspot](hotspot-proxy.md#configuration-file)). +- Por cada cliente hotspot, asigna un puerto UDP en **`PORT`…`PORT+GENERATOR-1`** (**`PORT`** + **`GENERATOR`** en YAML, alineados con **`adn-server`**) y reenvía a **`MASTER`**. - Cuando **self-service** actualiza **`Clients.options`** y pone **`modified=1`**, el proxy envía **RPTO** al **master** en un temporizador (~10 s). El **peer server** aplica entonces las opciones al camino del hotspot (ver [Self-service](self-service.md)). -**Por qué no forma parte del binario del peer server:** comparte **`adn-mon.yaml`**, self-service MySQL e implantación con la pila del monitor — ver [Por qué va con el monitor](hotspot-proxy.md#why-it-ships-with-the-monitor-not-inside-the-peer-server). +**Por qué no forma parte del binario del peer server:** comparte implantación, **self-service** MySQL y empaquetado con la pila del monitor — ver [Por qué va con el monitor](hotspot-proxy.md#why-it-ships-with-the-monitor-not-inside-the-peer-server). **Detalle:** [Proxy hotspot](hotspot-proxy.md) (claves de config, rango de puertos del peer, arranque). ## Topología típica de despliegue ```text -[Hotspots] --UDP--> [Proxy :LISTEN_PORT] --UDP--> [Peer server :rango DESTPORT] +[Hotspots] --UDP--> [Proxy :LISTEN_PORT] --UDP--> [Peer server :PORT..PORT+GENERATOR-1] | v MySQL (Clients) diff --git a/docs/es/monitor/configuration.md b/docs/es/monitor/configuration.md index a922257..eeef905 100644 --- a/docs/es/monitor/configuration.md +++ b/docs/es/monitor/configuration.md @@ -1,6 +1,10 @@ -# Configuración (`adn-mon.yaml`) +# Configuración (`adn-monitor.yaml`) -Todos los componentes leen el **mismo** YAML (ruta por defecto a menudo `monitor/adn-mon.yaml`; se puede sobrescribir con **`ADN_CONFIG_PATH`**). El ejemplo del repositorio **adn-monitor** es la plantilla autoritativa; las claves siguientes coinciden con `monitor/adn-mon.yaml` y `monitor/src/adn_monitor/infrastructure/config_loader.py` (los nombres internos pueden diferir). +Este documento describe **`adn-monitor.yaml`**, usado por el **monitor Python** (`monitor/monitor.py`) y el **backend PHP** (`backend/public/index.php`). La ruta por defecto suele ser **`monitor/adn-monitor.yaml`** (sobrescribible con **`ADN_CONFIG_PATH`**). + +El **proxy hotspot** carga por defecto **otro** fichero — **`proxy/adn-proxy.yaml`** — ver [Proxy hotspot](hotspot-proxy.md). La sección **`SELF_SERVICE`** (MySQL / PBKDF2) debe ser **idéntica** en ambos YAML cuando se usan los dos. + +El ejemplo del repositorio **adn-monitor** (`monitor/adn-monitor.yaml.example`) es la plantilla del monitor; las claves siguientes coinciden con ese fichero y `monitor/src/adn_monitor/infrastructure/config_loader.py` (los nombres internos pueden diferir). --- @@ -27,6 +31,7 @@ Debe coincidir con la configuración de informes del **ADN DMR Peer Server**. |-------|-------------| | **ADN_IP** | Host/IP donde está el **listener TCP de informes** del peer server (vista de red desde el monitor). | | **ADN_PORT** | Puerto TCP — debe ser igual a **`REPORTS.REPORT_PORT`** en el servidor y ser alcanzable. | +| **HELLO_TIMEOUT_MS** | Tras conectar por TCP, tiempo de espera del opcode **`0xFF` HELLO** (JSON) desde **new-adn-server**. Si no llega a tiempo, el monitor trata el peer como **legado** (solo CONFIG/BRIDGE pickle). Por defecto **1500** ms. Ver [Monitor e informes](../server/user-guide/monitoring.md). | --- @@ -45,13 +50,16 @@ Si el backend PHP no puede conectar, las rutas de **auth** y **self-service** no ## `PROXY` -**Proxy UDP hotspot** — guía completa: [Proxy hotspot](hotspot-proxy.md). Resumen: reenvía cada cliente a **`MASTER:DESTPORT_START`…`DEST_PORT_END`**; el peer server debe **escuchar** en esa IP y rango de puertos (ver también [Arquitectura](architecture.md)). +**Proxy UDP hotspot** — guía completa: [Proxy hotspot](hotspot-proxy.md). En los despliegues actuales, estas claves están en **`proxy/adn-proxy.yaml`**, no en `adn-monitor.yaml`. **Legado:** un único fichero puede seguir incluyendo **PROXY** si el proxy se arranca con **`ADN_CONFIG_PATH`** apuntando a ese fichero (ver orden de resolución en [Proxy hotspot](hotspot-proxy.md#configuration-file)). + +Resumen: **`PORT`** + **`GENERATOR`** deben coincidir con **`SYSTEM.PORT`** + **`SYSTEM.GENERATOR`** en `adn-server`; cada cliente se reenvía a **`MASTER`** en un puerto UDP dentro de **`PORT`…`PORT+GENERATOR-1`** (ver también [Arquitectura](architecture.md)). | Clave | Significado | |-------|-------------| | **MASTER** | Host del peer server (IP o DNS; resuelto al arrancar el proxy). | | **LISTEN_PORT** / **LISTEN_IP** | Dónde el proxy acepta UDP del hotspot (IP vacía suele significar todas las interfaces). | -| **DESTPORT_START** / **DEST_PORT_END** | Un puerto por cliente proxy hacia **`MASTER`**. | +| **PORT** / **DESTPORT_START** | Puerto UDP base en **`MASTER`** (el mismo que **PORT** del SYSTEM en el servidor). | +| **GENERATOR** | Cantidad de puertos UDP consecutivos en **`MASTER`** (el mismo entero que **GENERATOR** del SYSTEM en el servidor). | | **TIMEOUT**, **STATS**, **DEBUG**, **CLIENT_INFO** | Comportamiento y registro. | | **BLACK_LIST** / **IP_BLACK_LIST** | Listas de bloqueo opcionales. | @@ -74,10 +82,11 @@ Misma idea que en el peer server: descargar JSON de **peer / subscriber / TGID** | Clave | Significado | |-------|-------------| | **LOG_PATH** | Directorio de ficheros de log. | -| **LOG_FILE** | Nombre del log del monitor (p. ej. `adn-mon.log`). | -| **PROXY_LOG_FILE** | Nombre de log separado para el proxy (cuando se ejecuta con logging del proxy). | +| **LOG_FILE** | Nombre del log del monitor (p. ej. `adn-monitor.log`). | | **LOG_LEVEL** | p. ej. `INFO`, `DEBUG`. | +El nombre del fichero de log del **proxy hotspot** se define en **`proxy/adn-proxy.yaml`** dentro de **LOGGER** como **`PROXY_LOG_FILE`** (ver [Proxy hotspot](hotspot-proxy.md)). + --- ## `WEBSOCKET_SERVER` @@ -107,7 +116,8 @@ Misma idea que en el peer server: descargar JSON de **peer / subscriber / TGID** ## Entorno -- **`ADN_CONFIG_PATH`**: ruta absoluta a `adn-mon.yaml` para monitor, backend y proxy. +- **`ADN_CONFIG_PATH`**: ruta absoluta a **`adn-monitor.yaml`** para el **monitor** y el **backend PHP**. +- **`ADN_PROXY_CONFIG_PATH`** (opcional): ruta absoluta a **`adn-proxy.yaml`** para el proxy hotspot. Si no está definida, el proxy usa **`ADN_CONFIG_PATH`** (fichero combinado legado), luego **`proxy/adn-proxy.yaml`** por defecto — detalles en [Proxy hotspot](hotspot-proxy.md#configuration-file). - El backend puede usar **`API_BASE_PATH`** si la API va bajo un prefijo. --- diff --git a/docs/es/monitor/hotspot-proxy.md b/docs/es/monitor/hotspot-proxy.md index 8841730..4054ac6 100644 --- a/docs/es/monitor/hotspot-proxy.md +++ b/docs/es/monitor/hotspot-proxy.md @@ -8,7 +8,7 @@ Estructura: `proxy/proxy.py`, paquete `proxy/src/adn_proxy/` (arquitectura limpi No hay un despliegue obligatorio único, pero **hoy el proxy vive en el repo adn-monitor** a propósito: -- **Misma config y operativa** que el panel: **`adn-mon.yaml`**, **`ADN_CONFIG_PATH`**, y normalmente el mismo host que **PHP** y **MySQL**. +- **Mismo despliegue** que el panel: **`ADN_CONFIG_PATH`** / **`ADN_PROXY_CONFIG_PATH`**, **`adn-monitor.yaml`** + **`adn-proxy.yaml`**, y normalmente el mismo host que **PHP** y **MySQL**. - El **self-service** (**`Clients`**, RPTO, **`modified`**) está montado sobre ese ecosistema; el binario del peer server no posee esa base de datos ni el bloque **`PROXY`**. - **División de roles:** el **ADN DMR Peer Server** es el **núcleo de radio** (HBP/OpenBridge, bridges, voz, informes TCP). El proxy hotspot es un **frente UDP opcional** hacia un MASTER que ya escucha en un **rango** de puertos — útil cuando muchos hotspots comparten una dirección pública. @@ -16,34 +16,40 @@ No hay un despliegue obligatorio único, pero **hoy el proxy vive en el repo adn --- -## Fichero de configuración (igual que el monitor) +## Fichero de configuración {#configuration-file} -El proxy **no** usa `adn-server.yaml`. Lee el YAML del **monitor**: +El proxy **no** usa `adn-server.yaml`. Lee un YAML que incluye **`PROXY`**, **`SELF_SERVICE`** y **`LOGGER`** (log del proxy). -| Origen | Uso | -|--------|-----| -| **`ADN_CONFIG_PATH`** | Variable de entorno: ruta absoluta a **`adn-mon.yaml`** (compartida con **monitor**, **backend PHP**, **`.env`** opcional en la raíz del repo). | -| **`python proxy/proxy.py --config /ruta/a/adn-mon.yaml`** | Sobrescribe la ruta solo para este proceso. | -| **Por defecto** (sin definir) | `../monitor/adn-mon.yaml` relativo al directorio `proxy/` al ejecutar desde el árbol adn-monitor. | +### Orden de resolución -Secciones usadas: +| Prioridad | Origen | Uso | +|-----------|--------|-----| +| 1 | **`python proxy/proxy.py --config /ruta/fichero.yaml`** | Sobrescribe la ruta solo para este proceso. | +| 2 | **`ADN_PROXY_CONFIG_PATH`** | Variable opcional: ruta absoluta a **`adn-proxy.yaml`** (config dedicada del proxy). | +| 3 | **`ADN_CONFIG_PATH`** | Legado: ruta a un **fichero combinado** (p. ej. **`adn-monitor.yaml`** con **PROXY** incrustado — igual que monitor/backend). | +| 4 | **Por defecto** | **`proxy/adn-proxy.yaml`** junto a `proxy/proxy.py` si no hay variables de entorno. | + +Copia **`proxy/adn-proxy.example.yaml`** a **`proxy/adn-proxy.yaml`** y edita. **`SELF_SERVICE`** debe coincidir con **`monitor/adn-monitor.yaml`** (mismas credenciales MySQL y PBKDF2). + +Secciones leídas del fichero elegido: - **`PROXY`** — dirección de escucha, host master, **rango** de puertos de destino, timeouts, debug, listas negras. - **`SELF_SERVICE`** — MySQL y **`USE_SELFSERVICE`** (tabla **`Clients`**, RPTO / opciones). -- **`LOGGER`** — **`LOG_PATH`** y **`PROXY_LOG_FILE`** (log del proxy separado de **`LOG_FILE`** de `monitor.py`). +- **`LOGGER`** — **`LOG_PATH`** y **`PROXY_LOG_FILE`** (separado del **`LOG_FILE`** de `adn-monitor.yaml` para `monitor.py`). **Entorno** opcional (ver `proxy/README.md` en el repo): p. ej. **`ADN_PROXY_DEBUG`**, **`ADN_PROXY_LISTENPORT`**. --- -## Claves `PROXY` (`adn-mon.yaml`) +## Claves `PROXY` (en `adn-proxy.yaml`, o YAML combinado legado) | Clave | Rol | |-------|-----| | **MASTER** | IP o **nombre de host** del **ADN DMR Peer Server**. Se resuelve a IPv4 al arrancar (Twisted necesita IP para `write()`). | | **LISTEN_PORT** | Puerto UDP donde los **hotspots** se conectan **al proxy** (lo que configuran en el hotspot). | | **LISTEN_IP** | Vacío suele significar todas las interfaces; si no, enlazar a esa dirección. | -| **DESTPORT_START** / **DEST_PORT_END** | Rango inclusivo de puertos UDP en **`MASTER`**, **uno por hotspot** proxy (asignación secuencial dentro del proxy). | +| **PORT** / **DESTPORT_START** | Puerto UDP base en **`MASTER`** (alias **DESTPORT_START**); debe coincidir con **`SYSTEM.PORT`** en `adn-server`. | +| **GENERATOR** | El mismo entero que **`SYSTEM.GENERATOR`**; puertos UDP **`PORT`…`PORT+GENERATOR-1`** en **`MASTER`** (uno por sesión de hotspot proxy). | | **TIMEOUT** | Tiempo de inactividad / sesión (segundos). | | **STATS** | Registro extra de estadísticas. | | **DEBUG** | Log detallado de paquetes (o **`ADN_PROXY_DEBUG=1`**). | @@ -56,12 +62,12 @@ Las claves internas tras la carga usan nombres mixtos (`Master`, `ListenPort`, ## El peer server (`adn-server.yaml`) debe cubrir el rango de puertos -El proxy reenvía tráfico a **`MASTER:DESTPORT`** por cliente, con **DESTPORT** en **[DESTPORT_START, DEST_PORT_END]**. +El proxy reenvía tráfico a **`MASTER:puerto_asignado`** por cliente; **puerto_asignado** se elige en **`PORT`…`PORT+GENERATOR-1`** (la misma semántica de **PORT**/**GENERATOR** que en [Configuración del servidor](../server/user-guide/configuration.md)). -El **ADN DMR Peer Server** debe **escuchar UDP** en **ese host** en **cada puerto** del rango que vayas a usar (un listener **MASTER** por puerto, o equivalente). +El **ADN DMR Peer Server** debe **escuchar UDP** en **ese host** en **cada puerto** de ese rango (normalmente mediante **`GENERATOR`** en un bloque SYSTEM). -- Un único `MODE: MASTER` con un solo **`PORT`** **no** basta para varios clientes proxy si usan **DESTPORT** distintos — hacen falta **varios listeners** en el rango. -- Enfoques típicos: **`GENERATOR`** en un sistema MASTER (se parte en `NAME-0`, `NAME-1`, … con **PORT** consecutivos — ver [Configuración del servidor](../server/user-guide/configuration.md)), y/o varias entradas **`SYSTEMS`**, alineadas con **`DESTPORT_START`…`DEST_PORT_END`** en **`PROXY`**. +- Alinea **`PROXY.PORT`** y **`PROXY.GENERATOR`** con **`SYSTEM.PORT`** y **`SYSTEM.GENERATOR`** en **`adn-server.yaml`**. +- Configuración típica: un **`MODE: MASTER`** con **`GENERATOR`** que expande a `SYSTEM-0`…`SYSTEM-(N-1)` en puertos UDP consecutivos — ver [Configuración del servidor](../server/user-guide/configuration.md). Si el servidor solo escucha p. ej. en **56400** pero el proxy envía a **56401**, ese cliente no se registrará. @@ -69,18 +75,27 @@ Si el servidor solo escucha p. ej. en **56400** pero el proxy envía a **56401** ## Cómo arranca el proceso -1. Resolver ruta de config (`ADN_CONFIG_PATH`, `--config`, o por defecto). +1. Resolver ruta de config (`--config`, **`ADN_PROXY_CONFIG_PATH`**, **`ADN_CONFIG_PATH`**, o por defecto **`proxy/adn-proxy.yaml`**). 2. **`load_config()`** parsea YAML → **`PROXY`**, **`SELF_SERVICE`**, **`LOG`**. 3. Pool **MySQL** opcional si self-service / funciones de BD están activas. 4. El **reactor** Twisted ejecuta UDP **ProxyProtocol** en **`LISTEN_IP:LISTEN_PORT`**, reenviando a **`MASTER:puerto_destino_asignado`**. -Ejecución (desde la raíz de adn-monitor, con entorno): +Ejecución (desde la raíz de adn-monitor): ```bash -export ADN_CONFIG_PATH=/opt/adn-monitor/monitor/adn-mon.yaml +# YAML dedicado del proxy (recomendado) +export ADN_PROXY_CONFIG_PATH=/opt/adn-monitor/proxy/adn-proxy.yaml +python proxy/proxy.py + +# O usar por defecto proxy/adn-proxy.yaml tras copiar desde adn-proxy.example.yaml python proxy/proxy.py -# o -python proxy/proxy.py --config /ruta/a/adn-mon.yaml + +# Legado: un solo YAML combinado con el monitor +export ADN_CONFIG_PATH=/opt/adn-monitor/monitor/adn-monitor.yaml +python proxy/proxy.py + +# O ruta explícita para una ejecución +python proxy/proxy.py --config /opt/adn-monitor/proxy/adn-proxy.yaml ``` Usar **systemd** u otro supervisor junto a **`monitor.py`** y la pila **PHP**. @@ -103,12 +118,12 @@ Detalle: [Self-service](self-service.md) y **`proxy/README.md`** en adn-monitor. ## Visibilidad en el monitor -Los hotspots aparecen en el panel solo si el **peer server** envía **informes TCP** al mismo host/puerto que **`ADN_CONNECTION`** en **`adn-mon.yaml`**. Alinea **`REPORTS`** en el servidor con **`ADN_IP` / `ADN_PORT`**. Ver [Monitor e informes](../server/user-guide/monitoring.md). +Los hotspots aparecen en el panel solo si el **peer server** envía **informes TCP** al mismo host/puerto que **`ADN_CONNECTION`** en **`adn-monitor.yaml`**. Alinea **`REPORTS`** en el servidor con **`ADN_IP` / `ADN_PORT`**. Ver [Monitor e informes](../server/user-guide/monitoring.md). --- ## Ver también -- [Configuración del monitor](configuration.md) — referencia **`adn-mon.yaml`** (resumen PROXY). +- [Configuración del monitor](configuration.md) — **`adn-monitor.yaml`** (panel, informes, MySQL para backend/monitor); detalle **`PROXY`** arriba. - [Arquitectura](architecture.md) — dónde encaja el proxy en la pila. - [Self-service](self-service.md) — BD, **`modified`**, temporización RPTO. diff --git a/docs/es/monitor/index.md b/docs/es/monitor/index.md index 34948a7..4cc312d 100644 --- a/docs/es/monitor/index.md +++ b/docs/es/monitor/index.md @@ -9,32 +9,31 @@ Este capítulo documenta la pila **adn-monitor** con el mismo nivel de detalle q | Parte | Rol | |-------|-----| | **`monitor/monitor.py`** | Python (Twisted): se conecta al **puerto TCP de informes** del peer server, decodifica cargas netstring (`CONFIG_SND`, `BRIDGE_SND`, `BRDG_EVENT`), mantiene **CTABLE** / **BTABLE**, escribe **Last Heard** / estadísticas de TG en **MySQL** si está configurado, sirve JSON **WebSocket** al panel. | -| **`backend/`** | PHP **Slim**: `/api/config/dashboard`, auth, APIs **self-service** opcionales, proxy de alias. Lee el **mismo** `adn-mon.yaml` vía **`ADN_CONFIG_PATH`**. | +| **`backend/`** | PHP **Slim**: `/api/config/dashboard`, auth, APIs **self-service** opcionales, proxy de alias. Lee **`adn-monitor.yaml`** vía **`ADN_CONFIG_PATH`**. | | **`frontend/`** | React (Vite): UI del panel; consume API del backend + WebSocket. | -| **`proxy/`** | Python (Twisted): **proxy hotspot** UDP; reenvía Homebrew entre hotspots y el peer server; lee **`Clients`** en MySQL para opciones **RPTO** (self-service). | +| **`proxy/`** | Python (Twisted): **proxy hotspot** UDP; reenvía Homebrew entre hotspots y el peer server; lee **`Clients`** en MySQL para opciones **RPTO** (self-service). Carga **`adn-proxy.yaml`** por defecto (ver [Proxy hotspot](hotspot-proxy.md)). | -## Un solo fichero de configuración +## Ficheros de configuración -**`adn-mon.yaml`** (ruta a menudo con **`ADN_CONFIG_PATH`** en `.env`) lo comparten: +| Fichero | Quién lo usa | Variable típica | +|---------|----------------|-----------------| +| **`monitor/adn-monitor.yaml`** | **`monitor.py`**, **backend PHP** | **`ADN_CONFIG_PATH`** | +| **`proxy/adn-proxy.yaml`** | **`proxy/proxy.py`** | **`ADN_PROXY_CONFIG_PATH`** (opcional; valores por defecto y legado en [Proxy hotspot](hotspot-proxy.md#configuration-file)) | -- Monitor Python (`monitor.py`) -- Backend PHP (`backend/public/index.php`) -- Proxy hotspot (`proxy/proxy.py`) - -Un **único** YAML define direcciones de informes, textos del panel, puerto WebSocket, credenciales **SELF_SERVICE** de la BD y ajustes **PROXY** de escucha/rango. +**`SELF_SERVICE`** (MySQL / PBKDF2) debe **coincidir** entre ambos YAML cuando separas la config. **`ADN_CONNECTION`**, panel, WebSocket y alias van en **`adn-monitor.yaml`**; los ajustes **`PROXY`** de escucha/master/rango van en **`adn-proxy.yaml`**, salvo que uses un **fichero único legado** vía **`ADN_CONFIG_PATH`** para el proxy. ## Enlace con el peer server -| Servidor (`adn-server.yaml`) | Monitor (`adn-mon.yaml`) | +| Servidor (`adn-server.yaml`) | Monitor (`adn-monitor.yaml`) | |------------------------------|---------------------------| | **`REPORTS.REPORT_CLIENTS`** — lista de IPs permitidas para conectar **al** listener de informes, o el host del monitor | **`ADN_CONNECTION.ADN_IP`** / **`ADN_PORT`** — a dónde **se conecta** el monitor (debe coincidir con el bind y puerto de informes del servidor). | | **`REPORTS.REPORT_PORT`** — puerto TCP en el que el **servidor escucha** conexiones de informes | El mismo puerto que **`ADN_PORT`**. | -Ver [Monitor e informes](../server/user-guide/monitoring.md) para los opcodes de informes y [Configuración del monitor](configuration.md) para cada sección de `adn-mon.yaml`. +Ver [Monitor e informes](../server/user-guide/monitoring.md) para los opcodes de informes y [Configuración del monitor](configuration.md) para cada sección de `adn-monitor.yaml`. ## Ver también - [Proxy hotspot](hotspot-proxy.md) — `PROXY`, rango de puertos del peer, carga de config y arranque - [Arquitectura e implantación](architecture.md) -- [Configuración (`adn-mon.yaml`)](configuration.md) +- [Configuración (`adn-monitor.yaml`)](configuration.md) - [Self-service](self-service.md) diff --git a/docs/es/monitor/self-service.md b/docs/es/monitor/self-service.md index af50c81..07331fe 100644 --- a/docs/es/monitor/self-service.md +++ b/docs/es/monitor/self-service.md @@ -8,7 +8,7 @@ Intervienen **cuatro** piezas: **MySQL** (tabla `Clients`), **API PHP** (sesión ## Requisitos previos -1. Bloque **`SELF_SERVICE`** en **`adn-mon.yaml`** con credenciales **MySQL** válidas y parámetros **PBKDF2** alineados con tu herramienta de contraseñas (misma sal/iteraciones que **`hotspot_proxy_self_service.py`** cuando se use). +1. Bloque **`SELF_SERVICE`** en **`adn-monitor.yaml`** con credenciales **MySQL** válidas y parámetros **PBKDF2** alineados con tu herramienta de contraseñas (misma sal/iteraciones que **`hotspot_proxy_self_service.py`** cuando se use). 2. **`DASHBOARD.SELF_SERVICE: true`** para que la UI muestre la entrada **Self-service** (y el backend exponga `/api/self-service/*` cuando la BD conecta). 3. Tabla **`Clients`** con filas: **`callsign`**, **`int_id`** (ID DMR), **`psswd`** (hex PBKDF2-SHA256), **`options`** (línea `KEY=value` separada por `;`), **`logged_in`**, **`host`**, **`modified`**, etc. (ver esquema / migraciones en el repo adn-monitor). 4. El tráfico del hotspot debe pasar por el **proxy** si dependes de **`modified`** y del envío **RPTO** (ver flujo abajo). diff --git a/docs/es/server/contributing/translations.md b/docs/es/server/contributing/translations.md index 885877e..c8404ef 100644 --- a/docs/es/server/contributing/translations.md +++ b/docs/es/server/contributing/translations.md @@ -10,7 +10,7 @@ Las páginas **MkDocs** existen en árboles paralelos: | Español | **`docs/es/`** | **`mkdocs.es.yml`** → **`site/es/`** | - **`docs/en/server/`** — ADN DMR Peer Server (guía de usuario, protocolos, desarrollo, contribución). -- **`docs/en/monitor/`** — ADN Monitor (panel, `adn-mon.yaml`, self-service). +- **`docs/en/monitor/`** — ADN Monitor (panel, `adn-monitor.yaml`, self-service). El español replica las mismas rutas relativas bajo **`docs/es/`**. diff --git a/docs/es/server/user-guide/attribution.md b/docs/es/server/user-guide/attribution.md index bcf135b..153a7a1 100644 --- a/docs/es/server/user-guide/attribution.md +++ b/docs/es/server/user-guide/attribution.md @@ -2,7 +2,7 @@ ## Créditos y origen -**ADN Systems DMR Peer Server** parte de **FreeDMR**, reorganizado con **arquitectura limpia** (dominio, aplicación, infraestructura) y con funciones propias de ADN: anuncios programados, **TTS**, voz bajo demanda, fusión de **`adn-voice.yaml`**, informes TCP al **ADN Monitor**, integración con **`adn-mon.yaml`**, self-service y proxy hotspot, entre otras. +**ADN Systems DMR Peer Server** parte de **FreeDMR**, reorganizado con **arquitectura limpia** (dominio, aplicación, infraestructura) y con funciones propias de ADN: anuncios programados, **TTS**, voz bajo demanda, fusión de **`adn-voice.yaml`**, informes TCP al **ADN Monitor**, integración con **`adn-monitor.yaml`**, self-service y proxy hotspot, entre otras. **[FreeDMR Peer Server](https://gitlab.hacknix.net/hacknix/FreeDMR)** es obra de **Simon Adlem, G7RZU** ([hacknix](https://gitlab.hacknix.net/hacknix/FreeDMR)). El proyecto se describe así: diff --git a/docs/es/server/user-guide/introduction.md b/docs/es/server/user-guide/introduction.md index c03a4a9..d258b21 100644 --- a/docs/es/server/user-guide/introduction.md +++ b/docs/es/server/user-guide/introduction.md @@ -32,5 +32,5 @@ Enrutado, temporizadores, control de bucle OpenBridge y manejo de protocolo est - [Configuración](configuration.md) — ficheros, `GLOBAL`, **MASTER** / **PEER** / **OPENBRIDGE**, ACL, informes, alias, fusión de voz. - [Bridges y talkgroups](bridges-and-talkgroups.md) — cómo funciona `BRIDGES`. - [Números especiales](special-numbers.md) — TG 4000, servicios de información, eco. -- [ADN Monitor](../../monitor/index.md) — panel, `adn-mon.yaml`, self-service (repo aparte, desplegado con el servidor). +- [ADN Monitor](../../monitor/index.md) — panel, `adn-monitor.yaml`, self-service (repo aparte, desplegado con el servidor). - [Créditos y licencia](attribution.md) — ADN → FreeDMR → hblink3, licencia. diff --git a/docs/es/server/user-guide/monitoring.md b/docs/es/server/user-guide/monitoring.md index 2d0c092..875ac9c 100644 --- a/docs/es/server/user-guide/monitoring.md +++ b/docs/es/server/user-guide/monitoring.md @@ -4,13 +4,30 @@ Cuando **`REPORTS`** está habilitado en la config del servidor, el **ADN DMR Peer Server** escucha en TCP y los **clientes de informes** (típicamente **adn-monitor**) se conectan y reciben: -- **CONFIG_SND** / **BRIDGE_SND** — instantáneas pickle de sistemas y bridges. +- **HELLO** (opcode **`0xFF`**) — JSON enviado **el primero** en cada conexión TCP por **new-adn-server** (`adn-server`): nombre **`server`**, **`version`** del paquete, número de **`protocol`** y lista **`features`** (p. ej. `INGRESS`, `END_TX_FORWARD`, `PUSH_ON_CONNECT`). Permite al monitor marcar la sesión como **v2** antes de las cargas pickle. +- **CONFIG_SND** / **BRIDGE_SND** — instantáneas pickle de sistemas y bridges (tras HELLO al conectar, y de nuevo en actualizaciones / petición). - **BRDG_EVENT** — eventos de texto para llamadas (`GROUP VOICE`, `PRIVATE VOICE`, etc.). +Las pilas antiguas (**legado** estilo `adn-dmr-server`) pueden **omitir** HELLO. **adn-monitor** espera hasta **`ADN_CONNECTION.HELLO_TIMEOUT_MS`** (ver [Configuración del monitor](../../monitor/configuration.md#adn_connection)); si no llega HELLO, asume informes **legacy**. + El **monitor** decodifica estos mensajes, actualiza **CTABLE** / **BTABLE** y (con MySQL configurado) persiste Last Heard / estadísticas. **Pila completa:** [Descripción general del ADN Monitor](../../monitor/index.md) (monitor Python, WebSocket, API PHP, proxy y self-service opcionales). +### Líneas de log del canal de informes (logger `adn-monitor`) + +Python usa el nombre de logger **`adn-monitor`** (ver **`LOGGER.LOG_FILE`** en `adn-monitor.yaml`). **INFO** típicos del cliente TCP de informes: + +| Prefijo / texto del log | Significado | +|-------------------------|-------------| +| `(REPORT) Connection to report server established` | Sesión TCP activa; arranca la espera de HELLO (**`HELLO_TIMEOUT_MS`**). | +| `(REPORT) stringReceived: HELLO opcode=ff …` | Trama HELLO cruda en el cable. | +| `(REPORT) HELLO received: mode=v2 server=… version=… features=…` | JSON HELLO parseado; sesión **v2** (**new-adn-server**). | +| `(REPORT) No HELLO in …s; assuming legacy adn-dmr-server …` | No hay **`0xFF`** antes del timeout — modo **legacy** (solo CONFIG/BRIDGE pickle). Normal si el peer es **`adn-dmr-server`** clásico. Si **sabes** que el servidor es **new-adn-server** y aún ves esto, revisa **`ADN_IP`** / **`ADN_PORT`**, **`REPORTS.REPORT_CLIENTS`**, cortafuegos, o sube un poco **`HELLO_TIMEOUT_MS`** en enlaces muy lentos. | +| `(REPORT) CONFIG applied: …` / `(REPORT) BRIDGES applied: …` | Instantáneas pickle aplicadas a CTABLE/BTABLE. | + +En **WARNING**: JSON HELLO inválido (`(REPORT) HELLO payload not valid JSON`), o **`Invalid GLOBAL.TIMEZONE`** si **`GLOBAL.TIMEZONE`** no es un nombre IANA válido. + ## Semántica del monitor en OpenBridge - **`GROUP VOICE,INGRESS,RX`** — primera aparición de un flujo en una pata OpenBridge (depuración; visibilidad completa en logs). @@ -26,4 +43,4 @@ El panel muestra el estado **operativo** desde **START** (canónico); el **log d ## Self-service y hotspots -Los operadores que editan **opciones de dispositivo** desde el panel usan el flujo **self-service** (MySQL **`Clients`**, proxy **RPTO**). Está documentado en [Self-service](../../monitor/self-service.md); **no** forma parte solo del binario del peer server. Para la configuración del **proxy hotspot** (`PROXY` en `adn-mon.yaml`), enlace al rango **UDP** del peer server y arranque del proceso, ver [Proxy hotspot](../../monitor/hotspot-proxy.md). +Los operadores que editan **opciones de dispositivo** desde el panel usan el flujo **self-service** (MySQL **`Clients`**, proxy **RPTO**). Está documentado en [Self-service](../../monitor/self-service.md); **no** forma parte solo del binario del peer server. Para la configuración del **proxy hotspot** (`PROXY` en **`adn-proxy.yaml`** por defecto), enlace al rango **UDP** del peer server y arranque del proceso, ver [Proxy hotspot](../../monitor/hotspot-proxy.md). diff --git a/mkdocs.es.yml b/mkdocs.es.yml index 54df403..7e4385d 100644 --- a/mkdocs.es.yml +++ b/mkdocs.es.yml @@ -68,7 +68,7 @@ nav: - Traducciones: server/contributing/translations.md - Monitor: - Descripción general: monitor/index.md - - Configuración (adn-mon.yaml): monitor/configuration.md + - Configuración (adn-monitor.yaml): monitor/configuration.md - Proxy hotspot: monitor/hotspot-proxy.md - Arquitectura e implantación: monitor/architecture.md - Self-service: monitor/self-service.md diff --git a/mkdocs.yml b/mkdocs.yml index 8f18fc1..e22d6f8 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -68,7 +68,7 @@ nav: - Translations: server/contributing/translations.md - Monitor: - Overview: monitor/index.md - - Configuration (adn-mon.yaml): monitor/configuration.md + - Configuration (adn-monitor.yaml): monitor/configuration.md - Hotspot proxy: monitor/hotspot-proxy.md - Architecture and deployment: monitor/architecture.md - Self-service: monitor/self-service.md diff --git a/src/adn_server/application/reporting_use_cases.py b/src/adn_server/application/reporting_use_cases.py index eb20227..95b6d07 100644 --- a/src/adn_server/application/reporting_use_cases.py +++ b/src/adn_server/application/reporting_use_cases.py @@ -59,6 +59,8 @@ class ReportingUseCases: systems_cfg = self._config.get("SYSTEMS", {}) now = time.time() for system_name, sys_cfg in systems_cfg.items(): + if not sys_cfg.get("ENABLED", True): + continue if sys_cfg.get("MODE") == "OPENBRIDGE" and sys_cfg.get("ENHANCED_OBP"): if "_bcka" not in sys_cfg: logger.warning("(ROUTER) not sending to system %s as KeepAlive never seen", system_name)