diff --git a/docs/en/README.md b/docs/en/README.md index e903f31..fa9ee37 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -43,12 +43,13 @@ More: [Introduction](server/user-guide/introduction.md). ## ADN Monitor -Dashboard, WebSocket live view, optional **PHP API**, **MySQL** self-service, and **hotspot proxy** — see [Monitor overview](monitor/index.md). +Dashboard, WebSocket live view, FastAPI API, **MySQL** self-service — see [Monitor overview](monitor/index.md). **Hotspot proxy** is integrated in **adn-server**. | I want to… | Start here | |------------|------------| | `adn-server.yaml` — integrated `PROXY` / `SELF_SERVICE` | [Hotspot proxy (integrated)](server/user-guide/hotspot-proxy.md) | -| `adn-monitor.yaml`, legacy `adn-proxy.yaml`, layout | [Monitor configuration](monitor/configuration.md), [Hotspot proxy](monitor/hotspot-proxy.md) | +| `adn-monitor.yaml`, layout | [Monitor configuration](monitor/configuration.md) | +| Integrated hotspot proxy | [Hotspot proxy](server/user-guide/hotspot-proxy.md) | | Standalone hotspot proxy (UDP port range) | [Hotspot proxy — standalone](monitor/hotspot-proxy.md#standalone-proxy-legacy-adn-monitor-repo) | | 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 a46ce5b..6d3cc33 100644 --- a/docs/en/monitor/architecture.md +++ b/docs/en/monitor/architecture.md @@ -4,59 +4,52 @@ Under `monitor/src/adn_monitor/`: -- **Domain** — value objects, errors, opcode types. -- **Application** — `MonitorState`, `process_message` in `monitor_controller.py`, alias service, Last Heard / TG count use cases, time formatting. -- **Infrastructure** — YAML `load_config`, Twisted **TCP client** (`ReportClientFactory`) to the peer server, **WebSocket** factory for the dashboard, MySQL repositories, pickle/json decoders for `CONFIG_SND` / `BRIDGE_SND`. +- **Domain** — value objects, errors, opcode types, `UserSession`. +- **Application** — `MonitorState`, report/dashboard use cases, auth and self-service, alias service, Last Heard / TG count. +- **Infrastructure** — YAML `load_config`, FastAPI (REST + `/ws`), TCP ingest (Twisted thread) or MQTT, MySQL repositories, pickle/json decoders. -The monitor **connects outbound** to **`ADN_CONNECTION.ADN_IP:ADN_PORT`** and receives length-prefixed (netstring-style) messages. It updates in-memory **CTABLE** (masters/peers/OpenBridge) and **BTABLE** (bridges), and persists **BRDG_EVENT** outcomes when MySQL is configured. +Composition root: `infrastructure/fastapi/composition.py` (`build_monitor_api`). -## Report protocol (from the peer server) +## Unified process (`monitor.py`) -Same opcodes as documented for the server: **CONFIG_SND**, **BRIDGE_SND**, **BRDG_EVENT**, etc. The monitor decodes and applies them in `process_message` — see [Monitoring and reports](../server/user-guide/monitoring.md). +Single uvicorn/FastAPI process: -## WebSocket +| Route / role | Content | +|--------------|---------| +| `/api/*` | Dashboard config, auth, self-service, alias/status proxies | +| `/ws` | `conf,` protocol — CTABLE, Last Heard, voice | +| Ingest (background) | `MONITOR_APP.INGEST`: `tcp` (client to `ADN_CONNECTION`) or `mqtt` | +| Aliases (background) | Download → import with staging + RENAME | -`monitor.py` runs a Twisted **WebSocket** on **`WEBSOCKET_SERVER.WEBSOCKET_PORT`**, pushing JSON snapshots at **`FREQUENCY`** so the React app updates without polling for core state. +Report ingest connects outbound to **`ADN_CONNECTION.ADN_IP:ADN_PORT`** (TCP) or subscribes to MQTT topics. It updates **CTABLE** / **BTABLE** and persists Last Heard when MySQL is configured. -## PHP backend +## Report protocol (from the peer server) -- **Slim 4** front controller: `backend/public/index.php`. -- 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)). -- **`/api/aliases/*`** — optional proxy to TG/bridge list URLs from **ALIASES**. +Legacy pickle, v1 HELLO, and v2 slim (`dashboard_state` + `voice_event`) — see [Monitoring and reports](../server/user-guide/monitoring.md). ## Frontend - **Vite + React** under `frontend/`; build produces static assets served by nginx/Apache or similar. -- Uses **`API_BASE`** (build-time) to reach the PHP API and **WebSocket URL** for live data. +- Dev: Vite proxies `/api` and `/ws` to `MONITOR_APP.LISTEN_PORT`. +- Production: nginx serves `frontend/dist/` and proxies `/api` + `/ws` to the same FastAPI port. ## Hotspot proxy **Integrated (default):** **`adn-server.py`** runs UDP fan-in from **`PROXY.LISTEN_PORT`** into **`PROXY.TARGET_SYSTEM`**; **`SELF_SERVICE`** in **`adn-server.yaml`** drives **RPTO** from MySQL **`Clients`**. See [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md). -**Standalone (legacy, adn-monitor repo):** - -- Entry: `proxy/proxy.py`; package `src/adn_proxy/` (domain / application / infrastructure). -- Reads **`PROXY`** and **`SELF_SERVICE`** from **`adn-proxy.yaml`** by default (or from a combined monitor YAML via **`ADN_CONFIG_PATH`** — see [Hotspot proxy](hotspot-proxy.md#configuration-file)). -- For each hotspot client, allocates a UDP port in **`PORT`…`PORT+GENERATOR-1`** 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). - -**Details:** [Hotspot proxy](hotspot-proxy.md) (integrated vs standalone, config keys, startup). +The standalone **`adn-proxy`** process was removed from the **adn-monitor** repository; use integrated **`PROXY`** only. ## Typical deployment topology ```text -[Hotspots] --UDP--> [Proxy :LISTEN_PORT] --UDP--> [Peer server :PORT..PORT+GENERATOR-1] +[Hotspots] --UDP--> [adn-server PROXY] --UDP--> [peer MASTER] | v MySQL (Clients) -[Peer server :REPORT_PORT] <--- TCP --- [monitor.py : connects as client] +[Peer server :REPORT_PORT] <--- TCP or MQTT --- [monitor.py ingest] -[Browser] --HTTPS--> [PHP API + static frontend] -[Browser] --WS----> [monitor WebSocket :9000] +[Browser] --HTTPS--> [Nginx: static frontend + proxy /api,/ws --> MONITOR_APP.LISTEN_PORT] ``` --- diff --git a/docs/en/monitor/configuration.md b/docs/en/monitor/configuration.md index afb2a2a..b58ec03 100644 --- a/docs/en/monitor/configuration.md +++ b/docs/en/monitor/configuration.md @@ -1,8 +1,8 @@ # Configuration (`adn-monitor.yaml`) -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`**). +This document describes **`adn-monitor.yaml`**, used by **`monitor/monitor.py`** (FastAPI: REST, WebSocket, report ingest). Default path is usually **`monitor/adn-monitor.yaml`** (override with **`ADN_CONFIG_PATH`**). -**Integrated hotspot proxy:** **`PROXY`** and **`SELF_SERVICE`** in **`adn-server.yaml`** (see [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md)). **Standalone (legacy):** **`proxy/adn-proxy.yaml`** — see [Hotspot proxy](hotspot-proxy.md). **`SELF_SERVICE`** (MySQL / PBKDF2) must stay **identical** across **`adn-server.yaml`**, **`adn-monitor.yaml`**, and legacy **`adn-proxy.yaml`** when used. +**Hotspot proxy** is configured in **`adn-server.yaml`** (`PROXY` + `SELF_SERVICE`) — see [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md). **`SELF_SERVICE`** (MySQL / PBKDF2) must stay **identical** between **`adn-server.yaml`** and **`adn-monitor.yaml`**. 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). @@ -37,31 +37,13 @@ Must match the **ADN DMR Peer Server** reporting configuration. ## `SELF_SERVICE` -MySQL credentials and PBKDF2 parameters for **login** and **`Clients`** table access. **PBKDF2_SALT** and **PBKDF2_ITERATIONS** must match **`hotspot_proxy_self_service.py`** (or your password-registration tool) so stored password hashes verify in PHP and Python. +MySQL credentials and PBKDF2 parameters for **login**, **self-service**, and **`Clients`** table access. **PBKDF2_SALT** and **PBKDF2_ITERATIONS** must match **`hotspot_proxy_self_service.py`** (or your password-registration tool) so stored password hashes verify in the monitor API and **adn-server** integrated proxy. | Key | Meaning | |-----|---------| -| **USE_SELFSERVICE** | Used by the **proxy** config loader to enable DB-backed options / self-service paths (see proxy README). | | **DB_SERVER**, **DB_USERNAME**, **DB_PASSWORD**, **DB_NAME**, **DB_PORT** | MySQL connection for **`Clients`** (and related) tables. | -If the PHP backend cannot connect, **auth** and **self-service** API routes are not registered (see `backend/public/index.php`). - ---- - -## `PROXY` - -Hotspot **UDP proxy** — full guide: [Hotspot proxy](hotspot-proxy.md). **Integrated** deployments use **`PROXY`** in **`adn-server.yaml`** (fan-in, no port range). **Standalone** layouts keep these keys in **`proxy/adn-proxy.yaml`** (or a legacy combined file via **`ADN_CONFIG_PATH`**). - -**Standalone 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). | -| **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. | +If MySQL is unavailable, **auth** and **self-service** API routes are not registered. --- @@ -73,7 +55,7 @@ Comma-separated **network IDs** (as strings). Traffic from those OpenBridge sour ## `ALIASES` -Similar idea to the peer server: download **peer / subscriber / TGID** JSON and optional checksums. Keys include **PATH**, **\*_FILE**, **\*_URL**, **STALE_HOURS**, **REVIEW_INTERVAL_MINUTES**, **CHECKSUM_***, **TG_LIST_URL**, **BRIDGE_LIST_URL** (backend proxy for frontend pages). +Similar idea to the peer server: download **peer / subscriber / TGID** JSON and optional checksums. Keys include **PATH**, **\*_FILE**, **\*_URL**, **STALE_HOURS**, **REVIEW_INTERVAL_MINUTES**, **CHECKSUM_***, **TG_LIST_URL**, **BRIDGE_LIST_URL** (API proxy for frontend pages). --- @@ -85,18 +67,24 @@ Similar idea to the peer server: download **peer / subscriber / TGID** JSON and | **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` + +## `MONITOR_APP` | Key | Meaning | |-----|---------| -| **WEBSOCKET_PORT** | Port for Twisted WebSocket pushing JSON state to browsers. | -| **FREQUENCY** | Push interval (seconds). | +| **LISTEN_HOST** | Bind address (`""` = all IPv4). | +| **LISTEN_PORT** | HTTP port (e.g. `8080`): `/api/*` and `/ws`. | +| **INGEST** | `tcp` (client to `ADN_CONNECTION`) or `mqtt` (broker topics). | +| **MQTT** | Required when `INGEST: mqtt` (`URL`, `TOPIC_PREFIX`, `QOS`). | +| **FREQUENCY** | Background periodic resync (seconds); live updates are event-driven. | | **CLIENT_TIMEOUT** | Drop idle WS clients after N seconds (`0` = disable). | -| **USE_SSL**, **SSL_PATH**, **SSL_CERTIFICATE**, **SSL_PRIVATEKEY** | Optional WSS. | +| **CORS_ORIGINS** | Allowed origins for dev (optional). | + +In production, Nginx proxies `/api` and `/ws` to **LISTEN_PORT**. No separate WebSocket port is needed. + +Obsolete **`WEBSOCKET_SERVER`** YAML (Twisted on a separate port) is ignored; use **`MONITOR_APP`**. --- @@ -107,7 +95,7 @@ The **hotspot proxy** log filename is set in **`proxy/adn-proxy.yaml`** under ** | **DASHTITLE** | Header title. | | **BACKGROUND** | Use `bk.jpg` background if `true`. | | **LANGUAGE** | Default UI language (`en`, `es`, …). | -| **SELF_SERVICE** | If `true`, the UI can show the **Self-service** nav entry (backend must expose API + DB). | +| **SELF_SERVICE** | If `true`, the UI can show the **Self-service** nav entry (monitor API + MySQL required). | | **SHOW_CONSOLE** | Show console page (call start/end messages). | | **MIN_DURATION** | Minimum call duration (seconds) for **dashboard** Last Heard table (Last Heard page may still show shorter). | | **nav_links**, **footer**, **news** | Optional structured links / marquee items. | @@ -116,9 +104,8 @@ The **hotspot proxy** log filename is set in **`proxy/adn-proxy.yaml`** under ** ## Environment -- **`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. +- **`ADN_CONFIG_PATH`**: Absolute path to **`adn-monitor.yaml`** for **`monitor.py`**. +- Project root **`.env`**: `VITE_API_BASE`, `VITE_DEFAULT_LANGUAGE` (frontend build); auto-loaded by `monitor.py` and `db_bootstrap.py`. --- diff --git a/docs/en/monitor/hotspot-proxy.md b/docs/en/monitor/hotspot-proxy.md index 3029dfe..1ae970f 100644 --- a/docs/en/monitor/hotspot-proxy.md +++ b/docs/en/monitor/hotspot-proxy.md @@ -1,138 +1,8 @@ -# Hotspot proxy +# Hotspot proxy (moved) -## Integrated proxy (current default) +The **standalone** `adn-proxy` process and **`proxy/`** tree were **removed** from the **adn-monitor** repository. -**ADN DMR Peer Server** ships an **integrated hotspot proxy** in **`adn-server.py`**. Configure **`PROXY`** and **`SELF_SERVICE`** in **`adn-server.yaml`** — see [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md). +Use the **integrated hotspot proxy** in **adn-server**: -- Hotspots connect to **`PROXY.LISTEN_PORT`** only (fan-in). -- Traffic injects into **`PROXY.TARGET_SYSTEM`** (inject-only MASTER, **`MAX_PEERS`**). -- MySQL self-service uses the same **`Clients`** table as this monitor stack. -- **Disable** standalone **`adn-proxy`** on the same host to avoid **`LISTEN_PORT`** conflicts. - ---- - -## Standalone proxy (legacy, adn-monitor repo) - -The **adn-monitor** repository still contains a **standalone UDP relay** (`proxy/proxy.py`). It maps each hotspot to a **dedicated destination port** on the peer server host (port **range** + **`GENERATOR`**). Use this layout only when you deliberately keep proxy separate from **`adn-server`**. - -Source layout: `proxy/proxy.py`, package `proxy/src/adn_proxy/` (clean architecture). **GPL v3** (derivative of Simon Adlem, G7RZU’s original proxy). - -### Why it also ships with the monitor - -- **Same deployment** as the dashboard stack: **`adn-monitor.yaml`**, **`adn-proxy.yaml`**, **PHP**, **MySQL**. -- Historical split: peer server = radio core; proxy = optional UDP front on a port **range**. -- New ADN deployments should prefer the **integrated** proxy unless you maintain an existing **`adn-proxy`** unit. - ---- - -## Configuration file {#configuration-file} - -The **standalone** proxy does **not** use `adn-server.yaml` for its own process. It reads YAML that contains **`PROXY`**, **`SELF_SERVICE`**, and **`LOGGER`** (proxy log). The **integrated** proxy reads those blocks from **`adn-server.yaml`** instead. - -### Resolution order - -| 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`** (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 (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. | -| **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`**). | -| **CLIENT_INFO** | Per-client info in logs. | -| **BLACK_LIST** / **IP_BLACK_LIST** | Block radio IDs or source IPs. | - -Internal config keys (after load) use mixed-case names (`Master`, `ListenPort`, …) — see `adn_proxy.infrastructure.config_loader`. - ---- - -## Peer server (`adn-server.yaml`) must cover the port range - -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 **listen on UDP** on **that host** for **every port** in that range (usually via **`GENERATOR`** on one SYSTEM block). - -- 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. - ---- - -## How the process starts - -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): - -```bash -# 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 - -# 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. - ---- - -## RPTO, options, and self-service - -The proxy **never** sends **RPTO** directly to the hotspot for self-service updates. It sends **RPTO to the MASTER** (peer server); the server updates bridge/options and the normal HBP path applies. - -| Event | Proxy behaviour | -|-------|------------------| -| ~**10 s** after hotspot login (**RPTC**) | Read **`Clients.options`** from DB → **RPTO** → master `(MASTER, dport)`. | -| Every ~**10 s** | Rows with **`modified = 1`** → **RPTO** → master, then clear **`modified`**. | -| Hotspot sends **RPTO** | Forward to master; DB updates as implemented. | - -Details: [Self-service](self-service.md) and the **adn-monitor** `proxy/README.md`. - ---- - -## 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-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) — **`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. +- [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md) — `PROXY` and `SELF_SERVICE` in **`adn-server.yaml`** +- [Monitor overview](index.md) — dashboard stack (`monitor.py` + React) diff --git a/docs/en/monitor/index.md b/docs/en/monitor/index.md index 6ef3e48..77f827d 100644 --- a/docs/en/monitor/index.md +++ b/docs/en/monitor/index.md @@ -1,6 +1,6 @@ # ADN Monitor (overview) -**ADN Monitor** is a separate project from the **ADN DMR Peer Server**, but the two are normally deployed **together**: the server sends **TCP reports** (config, bridges, call events) to the monitor; the monitor drives the **web dashboard** (React) and **WebSocket** live updates. Optional components include the **PHP API** (Slim), **MySQL** (self-service / device registry), and the **hotspot proxy** (UDP between hotspots and the peer server — **integrated in `adn-server.py`** by default; standalone `adn-proxy` remains for legacy layouts). +**ADN Monitor** is a separate project from the **ADN DMR Peer Server**, but the two are normally deployed **together**: the server sends **TCP reports** (or MQTT) to the monitor; the monitor drives the **web dashboard** (React) and **WebSocket** live updates. A single **`monitor.py`** process (FastAPI) serves **REST** (`/api/*`), **WebSocket** (`/ws`), and **report ingest**. Optional: **MySQL** (self-service / Last Heard) and **integrated hotspot proxy** in **`adn-server.py`**. This chapter documents the **adn-monitor** stack at the same level of detail as the server guides. Source code lives in the **adn-monitor** repository, not in the **adn-server** repository (where this documentation is maintained). @@ -8,20 +8,17 @@ 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 **`adn-monitor.yaml`** via **`ADN_CONFIG_PATH`**. | -| **`frontend/`** | React (Vite): dashboard UI; consumes backend API + WebSocket. | -| **`proxy/`** | Python (Twisted): **standalone** UDP hotspot proxy (legacy); forwards Homebrew between hotspots and the peer server port range; reads **`Clients`** in MySQL for **RPTO**. Prefer integrated **`PROXY`** in **`adn-server.yaml`** — see [Hotspot proxy](hotspot-proxy.md). | +| **`monitor/monitor.py`** | FastAPI: REST (`/api/*`), WebSocket (`/ws`), TCP or MQTT report ingest, **CTABLE** / Last Heard, self-service MySQL. | +| **`frontend/`** | React (Vite): dashboard UI; same-origin `/api` + `/ws`. | ## Configuration files | File | Used by | Typical env | |------|---------|-------------| | **`adn-server.yaml`** | **`adn-server.py`** (integrated **`PROXY`** / **`SELF_SERVICE`**) | `-c` / default path next to binary | -| **`monitor/adn-monitor.yaml`** | **`monitor.py`**, **PHP backend** | **`ADN_CONFIG_PATH`** | -| **`proxy/adn-proxy.yaml`** | **`proxy/proxy.py`** (legacy standalone) | **`ADN_PROXY_CONFIG_PATH`** (optional; see [Hotspot proxy](hotspot-proxy.md#configuration-file)) | +| **`monitor/adn-monitor.yaml`** | **`monitor.py`** | **`ADN_CONFIG_PATH`** | -**`SELF_SERVICE`** (MySQL / PBKDF2) must **match** between **`adn-server.yaml`** (integrated proxy), **`adn-monitor.yaml`**, and legacy **`adn-proxy.yaml`** when used. **`ADN_CONNECTION`**, dashboard, WebSocket, and aliases live in **`adn-monitor.yaml`**; integrated **`PROXY`** / **`SELF_SERVICE`** live in **`adn-server.yaml`**; standalone proxy settings remain in **`adn-proxy.yaml`**. +**`SELF_SERVICE`** (MySQL / PBKDF2) must **match** between **`adn-server.yaml`** and **`adn-monitor.yaml`**. **`ADN_CONNECTION`**, dashboard, WebSocket, and aliases live in **`adn-monitor.yaml`**; integrated **`PROXY`** lives in **`adn-server.yaml`** — see [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md). ## Link to the peer server @@ -34,7 +31,7 @@ See [Monitoring and reports](../server/user-guide/monitoring.md) for report opco ## See also -- [Hotspot proxy](hotspot-proxy.md) — `PROXY`, peer server port range, how the process loads config and runs +- [Hotspot proxy (integrated)](../server/user-guide/hotspot-proxy.md) — `PROXY` in `adn-server.yaml` - [Architecture and deployment](architecture.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 5c41609..a94ecca 100644 --- a/docs/en/monitor/self-service.md +++ b/docs/en/monitor/self-service.md @@ -2,14 +2,14 @@ **Self-service** lets a hotspot owner **log in** to the dashboard, **edit their device options** (static TG lists, default reflector, timer, language, etc.), and have those options **pushed to the ADN DMR Peer Server** without manually editing YAML on the server. -It involves **four** pieces: **MySQL** (`Clients` table), **PHP API** (session + REST), **React** (`/self-service` page), and the **hotspot proxy** (periodic **RPTO** to the master). The **peer server** is the component that ultimately applies **RPTO** / **OPTIONS** to the running bridge and hotspot behaviour. +It involves **four** pieces: **MySQL** (`Clients` table), **monitor API** (FastAPI session + REST), **React** (`/self-service` page), and the **integrated hotspot proxy** in **adn-server** (periodic **RPTO** to the master). The **peer server** is the component that ultimately applies **RPTO** / **OPTIONS** to the running bridge and hotspot behaviour. --- ## Prerequisites 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). +2. **`DASHBOARD.SELF_SERVICE: true`** so the UI shows the **Self-service** menu entry (and `monitor.py` 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). @@ -19,7 +19,7 @@ It involves **four** pieces: **MySQL** (`Clients` table), **PHP API** (session + | Endpoint | Purpose | |----------|---------| -| **`POST /api/auth/login`** | Body: `callsign`, `password`. Verifies **PBKDF2** hash against **`Clients.psswd`** for rows with **`logged_in = 1`**. On success: PHP session with **`user_id`**, **`int_ids`** (all DMR IDs for that callsign). | +| **`POST /api/auth/login`** | Body: `callsign`, `password`. Verifies **PBKDF2** hash against **`Clients.psswd`** for rows with **`logged_in = 1`**. On success: session cookie with **`user_id`**, **`int_ids`** (all DMR IDs for that callsign). | | **`GET /api/auth/login-by-ip`** | Optional: single user match for **`Clients.host`** = client IP (same session shape). | | **`POST /api/auth/logout`** | Clears session. | | **`GET /api/auth/me`** | Returns `{ callsign, int_ids, selected_int_id }` for the React app. | @@ -41,7 +41,7 @@ Session lifetime is extended on activity (**SelfServiceController** uses a long ## End-to-end flow (why options reach the hotspot) -1. User saves options in the web UI → **PHP** writes **`Clients.options`** and **`modified = 1`**. +1. User saves options in the web UI → **monitor API** writes **`Clients.options`** and **`modified = 1`**. 2. The **hotspot proxy** runs **`send_opts`** on a loop (~every **10 s**). For rows with **`modified = 1`**, it reads options from the DB, sends **RPTO** (options) **to the peer server** at **`(MASTER, assigned_dest_port)`**, then clears **`modified`** in the DB. 3. The **ADN DMR Peer Server** receives **RPTO** on the MASTER leg and updates its **OPTIONS** / bridge state (same path as a normal hotspot registration refresh). 4. The server pushes the appropriate signalling to the **hotspot** so static TG / reflector / timer settings take effect **without** a full hotspot restart (exact behaviour matches the HBP **OPTIONS** flow in the server). diff --git a/docs/en/server/protocols/report-v2.md b/docs/en/server/protocols/report-v2.md index 3313339..51217e6 100644 --- a/docs/en/server/protocols/report-v2.md +++ b/docs/en/server/protocols/report-v2.md @@ -6,7 +6,7 @@ Replace monitor snapshots that today use **pickle** (`CONFIG_SND`, `BRIDGE_SND`) and **CSV strings** (`BRDG_EVENT`) with **typed JSON** that any client can decode. -**Release policy:** **adn-server 1.0.x** + **adn-monitor 1.0.x** = report v1 (frozen tag pair). **2.x** server emits **report v2 only** (no pickle shim, no `dual`); **adn-monitor 2.x** is required on the same release line. +**Release policy:** **adn-server 1.0.x** + **adn-monitor 1.0.x** = report v1 (frozen tag pair). **2.x** server sends **HELLO** with `report_protocol: 2` and **v2 JSON only** (`TOPOLOGY_SND`, `ROUTING_TABLE_SND`, `VOICE_EVENT_SND`, `DELTA_SND`) — no duplicate pickle/CSV frames. **adn-monitor 2.x** is the polyglot consumer: it decodes v1 wire from legacy peers and v2 JSON from **adn-server 2.x**, mapping both into the same dashboard state for the UI. **adn-monitor 1.0.0** cannot decode v2 opcodes — upgrade the monitor line for **adn-server 2.x**. ## Transport (unchanged) diff --git a/docs/en/server/user-guide/hotspot-proxy.md b/docs/en/server/user-guide/hotspot-proxy.md index c68a458..0acc149 100644 --- a/docs/en/server/user-guide/hotspot-proxy.md +++ b/docs/en/server/user-guide/hotspot-proxy.md @@ -10,8 +10,7 @@ Configuration lives in **`adn-server.yaml`** under **`PROXY`** and optional **`S | Deployment | What to run | |------------|-------------| -| **Typical ADN stack** (monitor + dashboard + many Pi-Star hotspots) | **`adn-server.py`** with **`PROXY`** + **`SELF_SERVICE`** — disable the standalone **`adn-proxy`** unit to avoid port clashes on **`PROXY.LISTEN_PORT`**. | -| **Legacy / split config** | Standalone **`proxy/proxy.py`** in the **adn-monitor** repo — see [Hotspot proxy (standalone)](../../monitor/hotspot-proxy.md). | +| **Typical ADN stack** (monitor + dashboard + many Pi-Star hotspots) | **`adn-server.py`** with **`PROXY`** + **`SELF_SERVICE`**. | The integrated proxy uses **fan-in**: hotspots only need **`PROXY.LISTEN_PORT`** (e.g. **62031**). The target **MASTER** is **inject-only** — it does **not** bind its own UDP port for that system (no per-hotspot port range on the server host). @@ -68,7 +67,7 @@ Set **`MAX_PEERS`** on the target MASTER to the maximum concurrent proxied hotsp ## `SELF_SERVICE` keys -Same semantics as **`adn-monitor.yaml`** / legacy **`adn-proxy.yaml`** — shared **`Clients`** table, **`modified`** flag, **RPTO** toward the MASTER. +Same semantics as **`adn-monitor.yaml`** — shared **`Clients`** table, **`modified`** flag, **RPTO** toward the MASTER. | Key | Role | |-----|------| @@ -106,15 +105,8 @@ See [Configuration — hot reload](configuration.md#hot-reload-adn-serveryaml). --- -## Standalone proxy (legacy) - -The **adn-monitor** repository still ships **`proxy/proxy.py`** for deployments that keep a **separate** UDP relay and **`adn-proxy.yaml`**. Do **not** run both the integrated proxy and standalone **`adn-proxy`** on the same **`LISTEN_PORT`**. - ---- - ## See also - [Configuration](configuration.md) — full **`adn-server.yaml`** reference. - [Monitoring and reports](monitoring.md) — TCP reports, dashboard, log rotation. - [Self-service](../../monitor/self-service.md) — **`Clients`**, **RPTO** timing. -- [Hotspot proxy (standalone)](../../monitor/hotspot-proxy.md) — legacy **`adn-proxy`** layout. diff --git a/docs/en/server/user-guide/introduction.md b/docs/en/server/user-guide/introduction.md index 2a9ddab..236bc5c 100644 --- a/docs/en/server/user-guide/introduction.md +++ b/docs/en/server/user-guide/introduction.md @@ -27,7 +27,7 @@ Routing, timers, OpenBridge loop control, and protocol handling are implemented ## Related programs - **Parrot / playback** — separate entrypoint (`adn-parrot.py`) for record-and-playback; see [Parrot](parrot.md). -- **Standalone hotspot proxy** — legacy `adn-proxy` in the **adn-monitor** repo when not using the integrated proxy; see [Hotspot proxy (standalone)](../../monitor/hotspot-proxy.md). +- **Integrated hotspot proxy** — `PROXY` in **`adn-server.yaml`**; see [Hotspot proxy](hotspot-proxy.md). ## Next steps diff --git a/docs/en/server/user-guide/monitoring.md b/docs/en/server/user-guide/monitoring.md index 2976486..3cc97aa 100644 --- a/docs/en/server/user-guide/monitoring.md +++ b/docs/en/server/user-guide/monitoring.md @@ -16,7 +16,7 @@ Older stacks (**legacy** `adn-dmr-server`-style) may **omit** HELLO. **adn-monit 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). +**Full stack:** [ADN Monitor overview](../../monitor/index.md) (FastAPI monitor, WebSocket, self-service). ### Report channel log lines (`adn-monitor` logger) @@ -51,7 +51,6 @@ These processes handle **`SIGUSR2`** by reopening **`logging.FileHandler`** stre | Process | Typical config keys | |---------|---------------------| | **`adn-server`** / **`adn-parrot`** | **`LOGGER.LOG_FILE`** (integrated proxy logs appear in the same file) | -| **`adn-proxy`** (standalone, legacy) | **`LOG.PATH`** + **`LOG.LOG_FILE`** in `adn-proxy.yaml` — omit if using integrated **`PROXY`** in `adn-server.yaml` | | **`adn-monitor`** | **`LOG.PATH`** + **`LOG.LOG_FILE`** in `adn-monitor.yaml` | Example **`/etc/logrotate.d/adn`** fragment (adjust paths and service names): @@ -71,7 +70,7 @@ Example **`/etc/logrotate.d/adn`** fragment (adjust paths and service names): } ``` -Repeat **`postrotate`** with **`kill -USR2`** for **`adn-parrot`** and **`adn-monitor`** units if those logs are rotated on the same host. Add **`adn-proxy`** only when you still run the **standalone** proxy (not needed when proxy is integrated into **`adn-server`**). Use the correct **PID** (systemd **`MainPID`**, a pidfile, or **`kill`** targeting the process you manage). +Repeat **`postrotate`** with **`kill -USR2`** for **`adn-parrot`** and **`adn-monitor`** units if those logs are rotated on the same host. Use the correct **PID** (systemd **`MainPID`**, a pidfile, or **`kill`** targeting the process you manage). ## Requirements @@ -82,4 +81,4 @@ Repeat **`postrotate`** with **`kill -USR2`** for **`adn-parrot`** and **`adn-mo Operators editing **device options** from the dashboard use the **self-service** flow (MySQL **`Clients`**, **RPTO** toward the conference MASTER). In current **ADN DMR Peer Server** deployments this runs **inside `adn-server.py`**: configure **`SELF_SERVICE`** and **`PROXY`** in **`adn-server.yaml`** (see [Hotspot proxy](hotspot-proxy.md)). Dashboard semantics: [Self-service](../../monitor/self-service.md). -Legacy stacks may still use a **standalone** **`adn-proxy`** process and **`adn-proxy.yaml`** — see [Hotspot proxy (standalone)](../../monitor/hotspot-proxy.md). Do not run both on the same **`LISTEN_PORT`**. +Hotspot proxy logs are part of **`adn-server`** when **`PROXY`** is enabled — see [Hotspot proxy (integrated)](hotspot-proxy.md). diff --git a/docs/es/README.md b/docs/es/README.md index 22aeb50..aec91d2 100644 --- a/docs/es/README.md +++ b/docs/es/README.md @@ -42,12 +42,13 @@ Más: [Introducción](server/user-guide/introduction.md). ## ADN Monitor -Panel, **WebSocket** en vivo, **API PHP** opcional, **MySQL** self-service y **proxy hotspot** — ver [Descripción general del monitor](monitor/index.md). +Panel, **WebSocket** en vivo, API FastAPI, **MySQL** self-service — ver [Descripción general del monitor](monitor/index.md). El **proxy hotspot** está integrado en **adn-server**. | Quiero… | Empieza aquí | |---------|----------------| | `adn-server.yaml` — `PROXY` / `SELF_SERVICE` integrados | [Proxy hotspot (integrado)](server/user-guide/hotspot-proxy.md) | -| `adn-monitor.yaml`, `adn-proxy.yaml` legado, despliegue | [Configuración del monitor](monitor/configuration.md), [Proxy hotspot](monitor/hotspot-proxy.md) | +| `adn-monitor.yaml`, despliegue | [Configuración del monitor](monitor/configuration.md) | +| Proxy hotspot integrado | [Proxy hotspot](server/user-guide/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 a3e0159..f72758c 100644 --- a/docs/es/monitor/architecture.md +++ b/docs/es/monitor/architecture.md @@ -4,59 +4,50 @@ Bajo `monitor/src/adn_monitor/`: -- **Dominio** — objetos de valor, errores, tipos de opcode. -- **Aplicación** — `MonitorState`, `process_message` en `monitor_controller.py`, servicio de alias, casos de uso Last Heard / conteo TG, formato de hora. -- **Infraestructura** — `load_config` YAML, cliente Twisted **TCP** (`ReportClientFactory`) al peer server, fábrica **WebSocket** para el panel, repositorios MySQL, decodificadores pickle/json para `CONFIG_SND` / `BRIDGE_SND`. +- **Dominio** — entidades, errores, `Result`, opcodes, `UserSession`. +- **Aplicación** — `MonitorState`, casos de uso (auth, self-service, informes, dashboard), puertos (`AuthRepository`, `HttpFetcherPort`, …). +- **Infraestructura** — YAML, FastAPI (REST + `/ws`), ingest TCP (Twisted en hilo) o MQTT, MySQL, decodificadores de informes. -El monitor **sale hacia** **`ADN_CONNECTION.ADN_IP:ADN_PORT`** y recibe mensajes con prefijo de longitud (estilo netstring). Actualiza **CTABLE** (masters/peers/OpenBridge) y **BTABLE** (bridges) en memoria, y persiste resultados de **BRDG_EVENT** cuando MySQL está configurado. +El **composition root** está en `infrastructure/fastapi/composition.py` (`build_monitor_api`). -## Protocolo de informes (desde el peer server) - -Los mismos opcodes que en la documentación del servidor: **CONFIG_SND**, **BRIDGE_SND**, **BRDG_EVENT**, etc. El monitor los decodifica y aplica en `process_message` — ver [Monitor e informes](../server/user-guide/monitoring.md). +## Proceso unificado (`monitor.py`) -## WebSocket +Un solo proceso uvicorn/FastAPI: -`monitor.py` ejecuta un **WebSocket** Twisted en **`WEBSOCKET_SERVER.WEBSOCKET_PORT`**, enviando instantáneas JSON a **`FREQUENCY`** para que la app React actualice sin polling del estado principal. +| Ruta / rol | Contenido | +|------------|-----------| +| `/api/*` | Config dashboard, auth, self-service, proxy alias/status | +| `/ws` | Protocolo `conf,` — CTABLE, Last Heard, voz | +| Ingest (fondo) | `MONITOR_APP.INGEST`: `tcp` (cliente a `ADN_CONNECTION`) **o** `mqtt` (tópicos `state` + `voice_event`) | +| Alias (fondo) | Descarga → `FILES.PATH`; import con **staging + RENAME** (commits cada 10k en staging; swap breve); merge con commits cada 2k; **PK en `id`** | -## Backend PHP +## Protocolo de informes (desde el peer server) -- **Slim 4** front controller: `backend/public/index.php`. -- 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)). -- **`/api/aliases/*`** — proxy opcional a URLs de listas TG/bridge desde **ALIASES**. +Modos de ingest según el peer: legacy (pickle), v1 HELLO, v2 slim (`dashboard_state` + `voice_event`). Ver [Monitor e informes](../server/user-guide/monitoring.md). ## Frontend -- **Vite + React** bajo `frontend/`; el build genera estáticos servidos por nginx/Apache o similar. -- Usa **`API_BASE`** (build) para la API PHP y **URL del WebSocket** para datos en vivo. +- **Vite + React** en `frontend/`; build → `frontend/dist/`. +- Desarrollo: Vite hace proxy de `/api` y `/ws` a `MONITOR_APP.LISTEN_PORT` (p. ej. 8080). +- Producción: Nginx sirve estáticos y proxifica `/api` + `/ws` al mismo puerto FastAPI. ## Proxy hotspot -**Integrado (predeterminado):** **`adn-server.py`** ejecuta fan-in UDP desde **`PROXY.LISTEN_PORT`** hacia **`PROXY.TARGET_SYSTEM`**; **`SELF_SERVICE`** en **`adn-server.yaml`** impulsa **RPTO** desde MySQL **`Clients`**. Ver [Proxy hotspot (integrado)](../server/user-guide/hotspot-proxy.md). - -**Independiente (legado, repo adn-monitor):** - -- Entrada: `proxy/proxy.py`; paquete `src/adn_proxy/` (dominio / aplicación / infraestructura). -- Lee **`PROXY`** y **`SELF_SERVICE`** desde **`adn-proxy.yaml`** por defecto (o YAML combinado del monitor vía **`ADN_CONFIG_PATH`** — ver [Proxy hotspot](hotspot-proxy.md#configuration-file)). -- Por cada cliente hotspot, asigna un puerto UDP en **`PORT`…`PORT+GENERATOR-1`** 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). +**Integrado (predeterminado):** `adn-server.py` con `PROXY` + `SELF_SERVICE` en `adn-server.yaml`. Ver [Proxy hotspot integrado](../server/user-guide/hotspot-proxy.md). -**Detalle:** [Proxy hotspot](hotspot-proxy.md) (integrado vs independiente, claves, arranque). +El proceso **`adn-proxy`** independiente se eliminó del repositorio **adn-monitor**; usa solo **`PROXY`** integrado. -## Topología típica de despliegue +## Topología típica ```text -[Hotspots] --UDP--> [Proxy :LISTEN_PORT] --UDP--> [Peer server :PORT..PORT+GENERATOR-1] +[Hotspots] --UDP--> [adn-server PROXY] --UDP--> [peer MASTER] | v MySQL (Clients) -[Peer server :REPORT_PORT] <--- TCP --- [monitor.py : cliente que conecta] +[Peer :REPORT_PORT] <--- TCP o MQTT --- [monitor.py ingest] -[Navegador] --HTTPS--> [API PHP + frontend estático] -[Navegador] --WS----> [WebSocket del monitor :9000] +[Navegador] --HTTPS--> [Nginx: frontend/dist + proxy /api,/ws --> :8080] ``` --- diff --git a/docs/es/monitor/configuration.md b/docs/es/monitor/configuration.md index a90aacd..8e76741 100644 --- a/docs/es/monitor/configuration.md +++ b/docs/es/monitor/configuration.md @@ -1,8 +1,8 @@ # Configuración (`adn-monitor.yaml`) -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`**). +Este documento describe **`adn-monitor.yaml`**, usado por **`monitor.py`**. La ruta por defecto suele ser **`monitor/adn-monitor.yaml`** (sobrescribible con **`ADN_CONFIG_PATH`**). -**Proxy hotspot integrado:** **`PROXY`** y **`SELF_SERVICE`** en **`adn-server.yaml`** (ver [Proxy hotspot (integrado)](../server/user-guide/hotspot-proxy.md)). **Independiente (legado):** **`proxy/adn-proxy.yaml`** — ver [Proxy hotspot](hotspot-proxy.md). **`SELF_SERVICE`** (MySQL / PBKDF2) debe ser **idéntica** entre **`adn-server.yaml`**, **`adn-monitor.yaml`** y **`adn-proxy.yaml`** legado si se usa. +**Proxy hotspot** se configura en **`adn-server.yaml`** (`PROXY` + `SELF_SERVICE`) — ver [Proxy hotspot integrado](../server/user-guide/hotspot-proxy.md). **`SELF_SERVICE`** (MySQL / PBKDF2) debe ser **idéntica** entre **`adn-server.yaml`** y **`adn-monitor.yaml`**. 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). @@ -19,7 +19,7 @@ El ejemplo del repositorio **adn-monitor** (`monitor/adn-monitor.yaml.example`) | **EMPTY_MASTERS** | Mostrar masters sin peers. | | **TGCOUNT_INC** | Activar página / estadísticas de conteo de TG. | | **TGCOUNT_ROWS** | Filas para el conteo de TG. | -| **TIMEZONE** | Zona horaria IANA (p. ej. `America/Santiago`) para mostrar; vacío usa la hora local del servidor. | +| **TIMEZONE** | Zona horaria IANA (p. ej. `America/Santiago`): fechas Last Heard en pantalla; **TG Count** usa el **día calendario en esa zona** (medianoche local = nuevo día de estadísticas). Vacío → día UTC. | --- @@ -37,31 +37,13 @@ Debe coincidir con la configuración de informes del **ADN DMR Peer Server**. ## `SELF_SERVICE` -Credenciales MySQL y parámetros PBKDF2 para **login** y acceso a la tabla **`Clients`**. **PBKDF2_SALT** y **PBKDF2_ITERATIONS** deben coincidir con **`hotspot_proxy_self_service.py`** (o tu herramienta de registro de contraseñas) para que los hashes verifiquen en PHP y Python. +Credenciales MySQL y parámetros PBKDF2 para **login**, **self-service** y acceso a la tabla **`Clients`**. **PBKDF2_SALT** y **PBKDF2_ITERATIONS** deben coincidir con **`hotspot_proxy_self_service.py`** (o tu herramienta de registro de contraseñas) para que los hashes verifiquen en la API del monitor y en el proxy integrado de **adn-server**. | Clave | Significado | |-------|-------------| -| **USE_SELFSERVICE** | Lo usa el cargador de config del **proxy** para rutas con BD / self-service (ver README del proxy). | | **DB_SERVER**, **DB_USERNAME**, **DB_PASSWORD**, **DB_NAME**, **DB_PORT** | Conexión MySQL para **`Clients`** (y tablas relacionadas). | -Si el backend PHP no puede conectar, las rutas de **auth** y **self-service** no se registran (ver `backend/public/index.php`). - ---- - -## `PROXY` - -**Proxy UDP hotspot** — guía completa: [Proxy hotspot](hotspot-proxy.md). Los despliegues **integrados** usan **`PROXY`** en **`adn-server.yaml`** (fan-in, sin rango de puertos). Los layouts **independientes** mantienen estas claves en **`proxy/adn-proxy.yaml`** (o fichero combinado legado vía **`ADN_CONFIG_PATH`**). - -**Resumen independiente:** **`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). | -| **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. | +Si MySQL no está disponible, las rutas de **auth** y **self-service** no se registran. --- @@ -85,18 +67,25 @@ Misma idea que en el peer server: descargar JSON de **peer / subscriber / TGID** | **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` +## `MONITOR_APP` + +Proceso unificado **`monitor.py`**: REST y WebSocket en el **mismo** host/puerto. | Clave | Significado | |-------|-------------| -| **WEBSOCKET_PORT** | Puerto del WebSocket Twisted que envía estado JSON a los navegadores. | -| **FREQUENCY** | Intervalo de envío (segundos). | +| **LISTEN_HOST** | Interfaz de escucha (`""` = todas las IPv4). | +| **LISTEN_PORT** | Puerto HTTP (p. ej. `8080`): `/api/*` y `/ws`. | +| **INGEST** | `tcp` (cliente a `ADN_CONNECTION`) o `mqtt` (tópicos del broker). | +| **MQTT** | Obligatorio si `INGEST: mqtt` (`URL`, `TOPIC_PREFIX`, `QOS`). | +| **FREQUENCY** | Resync periódico en segundo plano (segundos); las actualizaciones en vivo son por eventos. | | **CLIENT_TIMEOUT** | Cerrar clientes WS inactivos tras N segundos (`0` = desactivado). | -| **USE_SSL**, **SSL_PATH**, **SSL_CERTIFICATE**, **SSL_PRIVATEKEY** | WSS opcional. | +| **CORS_ORIGINS** | Orígenes permitidos para desarrollo (opcional). | + +Nginx en producción proxifica `/api` y `/ws` a **LISTEN_PORT**. No hace falta un puerto WebSocket aparte. + +La sección obsoleta **`WEBSOCKET_SERVER`** en YAML (Twisted en puerto distinto) se ignora; usa **`MONITOR_APP`**. --- @@ -107,18 +96,38 @@ El nombre del fichero de log del **proxy hotspot** se define en **`proxy/adn-pro | **DASHTITLE** | Título de cabecera. | | **BACKGROUND** | Usar fondo `bk.jpg` si es `true`. | | **LANGUAGE** | Idioma por defecto de la UI (`en`, `es`, …). | -| **SELF_SERVICE** | Si es `true`, la UI puede mostrar la entrada **Self-service** (el backend debe exponer API + BD). | +| **SELF_SERVICE** | Si es `true`, la UI puede mostrar la entrada **Self-service** (API del monitor + MySQL). | | **SHOW_CONSOLE** | Mostrar página consola (mensajes inicio/fin de llamada). | | **MIN_DURATION** | Duración mínima de llamada (segundos) para la tabla Last Heard del **panel** (la página Last Heard puede seguir mostrando más cortas). | | **nav_links**, **footer**, **news** | Enlaces estructurados / marquee opcionales. | --- +## Esquema MySQL y migraciones + +No hay Alembic: el monitor usa **`schema_migrations`** y comprobaciones en **`information_schema`**. + +| Comando | Cuándo | +|---------|--------| +| `python db_bootstrap.py --config adn-monitor.yaml --create` | BD nueva | +| `python db_bootstrap.py --config adn-monitor.yaml --update` | BD existente (mismas operaciones, idempotente) | + +**`monitor.py`** ejecuta **`ensure_schema`** al arrancar si hay **`SELF_SERVICE`**: `CREATE TABLE IF NOT EXISTS`, migraciones pendientes y limpieza de tablas staging huérfanas (`*_import`, `*_old`). **No borra datos** de `subscriber_ids` ni de `Clients`. + +**Import masivo de alias (sin bloquear lecturas):** + +- Tablas con **PK en `id`** únicamente (lookups puntuales). +- **Replace:** carga en `{tabla}_import` con **commit cada 10 000 filas** (la tabla live sigue legible); swap atómico `RENAME TABLE` (bloqueo metadata breve). +- **Merge** (ficheros locales): `INSERT IGNORE` con **commit cada 2 000 filas**. + +Migraciones: `001_clients_callsign`, `002_clients_options_width`, `003_alias_pk_only`. + +--- + ## Entorno -- **`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. +- **`ADN_CONFIG_PATH`**: ruta absoluta a **`adn-monitor.yaml`** para **`monitor.py`**. +- **`.env`** en la raíz del repo: `VITE_API_BASE`, `VITE_DEFAULT_LANGUAGE` (build del frontend); se carga automáticamente en `monitor.py` y `db_bootstrap.py`. --- diff --git a/docs/es/monitor/hotspot-proxy.md b/docs/es/monitor/hotspot-proxy.md index fa229e2..6bf32e4 100644 --- a/docs/es/monitor/hotspot-proxy.md +++ b/docs/es/monitor/hotspot-proxy.md @@ -1,138 +1,8 @@ -# Proxy hotspot +# Proxy hotspot (trasladado) -## Proxy integrado (predeterminado actual) +El proceso **`adn-proxy`** independiente y el árbol **`proxy/`** se **eliminaron** del repositorio **adn-monitor**. -**ADN DMR Peer Server** incluye un **proxy hotspot integrado** en **`adn-server.py`**. Configura **`PROXY`** y **`SELF_SERVICE`** en **`adn-server.yaml`** — ver [Proxy hotspot (integrado)](../server/user-guide/hotspot-proxy.md). +Usa el **proxy hotspot integrado** en **adn-server**: -- Los hotspots se conectan solo a **`PROXY.LISTEN_PORT`** (fan-in). -- El tráfico se inyecta en **`PROXY.TARGET_SYSTEM`** (MASTER solo inyección, **`MAX_PEERS`**). -- El self-service MySQL usa la misma tabla **`Clients`** que este stack del monitor. -- **Desactiva** **`adn-proxy`** independiente en el mismo host para evitar conflictos en **`LISTEN_PORT`**. - ---- - -## Proxy independiente (legado, repo adn-monitor) - -El repositorio **adn-monitor** sigue teniendo un **relé UDP independiente** (`proxy/proxy.py`). Asigna a cada hotspot un **puerto de destino dedicado** en el host del peer server (rango de puertos + **`GENERATOR`**). Usa este layout solo si mantienes el proxy separado de **`adn-server`** a propósito. - -Estructura: `proxy/proxy.py`, paquete `proxy/src/adn_proxy/` (arquitectura limpia). **GPL v3** (derivado del proxy original de Simon Adlem, G7RZU). - -### Por qué también va con el monitor {#why-it-ships-with-the-monitor-not-inside-the-peer-server} - -- **Mismo despliegue** que el panel: **`adn-monitor.yaml`**, **`adn-proxy.yaml`**, **PHP**, **MySQL**. -- Separación histórica: peer server = núcleo radio; proxy = frontal UDP opcional en un **rango** de puertos. -- Los despliegues ADN nuevos deben preferir el proxy **integrado** salvo que mantengas una unidad **`adn-proxy`** existente. - ---- - -## Fichero de configuración {#configuration-file} - -El proxy **independiente** **no** usa `adn-server.yaml` para su propio proceso. Lee un YAML que incluye **`PROXY`**, **`SELF_SERVICE`** y **`LOGGER`** (log del proxy). El proxy **integrado** lee esos bloques desde **`adn-server.yaml`**. - -### Orden de resolución - -| 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`** (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` (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. | -| **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`**). | -| **CLIENT_INFO** | Información por cliente en logs. | -| **BLACK_LIST** / **IP_BLACK_LIST** | Bloquear IDs de radio o IPs de origen. | - -Las claves internas tras la carga usan nombres mixtos (`Master`, `ListenPort`, …) — ver `adn_proxy.infrastructure.config_loader`. - ---- - -## El peer server (`adn-server.yaml`) debe cubrir el rango de puertos - -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** de ese rango (normalmente mediante **`GENERATOR`** en un bloque SYSTEM). - -- 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á. - ---- - -## Cómo arranca el proceso - -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): - -```bash -# 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 - -# 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**. - ---- - -## RPTO, opciones y self-service - -El proxy **nunca** envía **RPTO** directamente al hotspot para actualizaciones self-service. Envía **RPTO al MASTER** (peer server); el servidor actualiza bridges/opciones y aplica el flujo HBP normal. - -| Evento | Comportamiento del proxy | -|--------|---------------------------| -| ~**10 s** tras login del hotspot (**RPTC**) | Leer **`Clients.options`** de la BD → **RPTO** → master `(MASTER, dport)`. | -| Cada ~**10 s** | Filas con **`modified = 1`** → **RPTO** → master, luego limpiar **`modified`**. | -| El hotspot envía **RPTO** | Reenvío al master; actualizaciones de BD según implementación. | - -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-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) — **`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. +- [Proxy hotspot integrado](../server/user-guide/hotspot-proxy.md) — `PROXY` y `SELF_SERVICE` en **`adn-server.yaml`** +- [Descripción general del monitor](index.md) — pila del panel (`monitor.py` + React) diff --git a/docs/es/monitor/index.md b/docs/es/monitor/index.md index 81bc4b5..42f9dd1 100644 --- a/docs/es/monitor/index.md +++ b/docs/es/monitor/index.md @@ -1,6 +1,6 @@ # ADN Monitor (descripción general) -**ADN Monitor** es un proyecto distinto del **ADN DMR Peer Server**, pero ambos suelen desplegarse **juntos**: el servidor envía **informes TCP** (config, bridges, eventos de llamada) al monitor; el monitor alimenta el **panel web** (React) y las actualizaciones **WebSocket**. Los componentes opcionales incluyen la **API PHP** (Slim), **MySQL** (self-service / registro de dispositivos) y el **proxy hotspot** (UDP entre hotspots y el peer server — **integrado en `adn-server.py`** por defecto; `adn-proxy` independiente queda para layouts legados). +**ADN Monitor** es un proyecto distinto del **ADN DMR Peer Server**, pero ambos suelen desplegarse **juntos**: el servidor envía **informes TCP** (o MQTT) al monitor; el monitor alimenta el **panel web** (React) y las actualizaciones **WebSocket**. Un único proceso **`monitor.py`** (FastAPI) sirve **REST** (`/api/*`), **WebSocket** (`/ws`) e **ingest** de informes. Opcional: **MySQL** (self-service / Last Heard) y **proxy hotspot** integrado en **`adn-server.py`**. Este capítulo documenta la pila **adn-monitor** con el mismo nivel de detalle que las guías del servidor. El código fuente está en el repositorio **adn-monitor**, no en el repositorio **adn-server** (donde se mantiene esta documentación). @@ -8,20 +8,17 @@ 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 **`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 **independiente** (legado); reenvía Homebrew entre hotspots y el rango de puertos del peer server; lee **`Clients`** en MySQL para **RPTO**. Preferir **`PROXY`** integrado en **`adn-server.yaml`** — ver [Proxy hotspot](hotspot-proxy.md). | +| **`monitor/monitor.py`** | FastAPI: REST (`/api/*`), WebSocket (`/ws`), ingest TCP o MQTT, estado **CTABLE** / Last Heard, self-service MySQL. | +| **`frontend/`** | React (Vite): UI del panel; mismo origen `/api` + `/ws`. | ## Ficheros de configuración | Fichero | Quién lo usa | Variable típica | |---------|----------------|-----------------| | **`adn-server.yaml`** | **`adn-server.py`** (**`PROXY`** / **`SELF_SERVICE`** integrados) | `-c` / ruta por defecto junto al binario | -| **`monitor/adn-monitor.yaml`** | **`monitor.py`**, **backend PHP** | **`ADN_CONFIG_PATH`** | -| **`proxy/adn-proxy.yaml`** | **`proxy/proxy.py`** (independiente legado) | **`ADN_PROXY_CONFIG_PATH`** (opcional; ver [Proxy hotspot](hotspot-proxy.md#configuration-file)) | +| **`monitor/adn-monitor.yaml`** | **`monitor.py`** | **`ADN_CONFIG_PATH`** | -**`SELF_SERVICE`** (MySQL / PBKDF2) debe **coincidir** entre **`adn-server.yaml`** (proxy integrado), **`adn-monitor.yaml`** y **`adn-proxy.yaml`** legado si se usa. **`ADN_CONNECTION`**, panel, WebSocket y alias van en **`adn-monitor.yaml`**; **`PROXY`** / **`SELF_SERVICE`** integrados van en **`adn-server.yaml`**; el proxy independiente sigue en **`adn-proxy.yaml`**. +**`SELF_SERVICE`** (MySQL / PBKDF2) debe **coincidir** entre **`adn-server.yaml`** y **`adn-monitor.yaml`**. **`ADN_CONNECTION`**, panel, WebSocket y alias van en **`adn-monitor.yaml`**; **`PROXY`** integrado va en **`adn-server.yaml`** — ver [Proxy hotspot integrado](../server/user-guide/hotspot-proxy.md). ## Enlace con el peer server @@ -34,7 +31,7 @@ Ver [Monitor e informes](../server/user-guide/monitoring.md) para los opcodes de ## Ver también -- [Proxy hotspot](hotspot-proxy.md) — `PROXY`, rango de puertos del peer, carga de config y arranque +- [Proxy hotspot (integrado)](../server/user-guide/hotspot-proxy.md) — `PROXY` en `adn-server.yaml` - [Arquitectura e implantación](architecture.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 07331fe..96a8227 100644 --- a/docs/es/monitor/self-service.md +++ b/docs/es/monitor/self-service.md @@ -2,14 +2,14 @@ **Self-service** permite al dueño de un hotspot **iniciar sesión** en el panel, **editar las opciones de su dispositivo** (listas estáticas de TG, reflector por defecto, temporizador, idioma, etc.) y que esas opciones se **envíen al ADN DMR Peer Server** sin editar YAML a mano en el servidor. -Intervienen **cuatro** piezas: **MySQL** (tabla `Clients`), **API PHP** (sesión + REST), **React** (página `/self-service`) y el **proxy hotspot** (**RPTO** periódico al master). El **peer server** es quien aplica al final **RPTO** / **OPTIONS** al bridge en ejecución y al comportamiento del hotspot. +Intervienen **cuatro** piezas: **MySQL** (tabla `Clients`), **API del monitor** (FastAPI, sesión + REST), **React** (página `/self-service`) y el **proxy hotspot integrado** en **adn-server** (**RPTO** periódico al master). El **peer server** es quien aplica al final **RPTO** / **OPTIONS** al bridge en ejecución y al comportamiento del hotspot. --- ## Requisitos previos 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). +2. **`DASHBOARD.SELF_SERVICE: true`** para que la UI muestre la entrada **Self-service** (y `monitor.py` 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). @@ -19,7 +19,7 @@ Intervienen **cuatro** piezas: **MySQL** (tabla `Clients`), **API PHP** (sesión | Endpoint | Uso | |----------|-----| -| **`POST /api/auth/login`** | Cuerpo: `callsign`, `password`. Verifica hash **PBKDF2** contra **`Clients.psswd`** en filas con **`logged_in = 1`**. Éxito: sesión PHP con **`user_id`**, **`int_ids`** (todos los DMR ID de ese indicativo). | +| **`POST /api/auth/login`** | Cuerpo: `callsign`, `password`. Verifica hash **PBKDF2** contra **`Clients.psswd`** en filas con **`logged_in = 1`**. Éxito: cookie de sesión con **`user_id`**, **`int_ids`** (todos los DMR ID de ese indicativo). | | **`GET /api/auth/login-by-ip`** | Opcional: una coincidencia de usuario por **`Clients.host`** = IP del cliente (misma forma de sesión). | | **`POST /api/auth/logout`** | Cierra sesión. | | **`GET /api/auth/me`** | Devuelve `{ callsign, int_ids, selected_int_id }` para React. | @@ -41,7 +41,7 @@ La sesión se prolonga con actividad (**SelfServiceController** usa un timeout l ## Flujo extremo a extremo (cómo llegan las opciones al hotspot) -1. El usuario guarda opciones en la web → **PHP** escribe **`Clients.options`** y **`modified = 1`**. +1. El usuario guarda opciones en la web → la **API del monitor** escribe **`Clients.options`** y **`modified = 1`**. 2. El **proxy hotspot** ejecuta **`send_opts`** en bucle (~cada **10 s**). Para filas con **`modified = 1`**, lee opciones de la BD, envía **RPTO** **al peer server** en **`(MASTER, puerto_destino_asignado)`**, luego limpia **`modified`** en la BD. 3. El **ADN DMR Peer Server** recibe **RPTO** en la pata MASTER y actualiza su estado **OPTIONS** / bridge (mismo camino que un refresco normal de registro del hotspot). 4. El servidor envía la señalización adecuada al **hotspot** para que TG estáticos / reflector / temporizador surtan efecto **sin** reinicio completo del hotspot (el comportamiento coincide con el flujo HBP **OPTIONS** del servidor). diff --git a/docs/es/server/user-guide/hotspot-proxy.md b/docs/es/server/user-guide/hotspot-proxy.md index ea4d85b..05276ae 100644 --- a/docs/es/server/user-guide/hotspot-proxy.md +++ b/docs/es/server/user-guide/hotspot-proxy.md @@ -10,8 +10,7 @@ La configuración está en **`adn-server.yaml`**, bloques **`PROXY`** y opcional | Despliegue | Qué ejecutar | |------------|--------------| -| **Stack ADN habitual** (monitor + panel + muchos hotspots Pi-Star) | **`adn-server.py`** con **`PROXY`** + **`SELF_SERVICE`** — desactiva la unidad **`adn-proxy`** independiente para evitar conflicto en **`PROXY.LISTEN_PORT`**. | -| **Legado / config separada** | **`proxy/proxy.py`** en el repo **adn-monitor** — ver [Proxy hotspot (independiente)](../../monitor/hotspot-proxy.md). | +| **Stack ADN habitual** (monitor + panel + muchos hotspots Pi-Star) | **`adn-server.py`** con **`PROXY`** + **`SELF_SERVICE`**. | El proxy integrado usa **fan-in**: los hotspots solo necesitan **`PROXY.LISTEN_PORT`** (p. ej. **62031**). El **MASTER** destino es **solo inyección** — **no** abre su propio puerto UDP para ese system (sin rango de puertos por hotspot en el host del servidor). @@ -68,13 +67,13 @@ Define **`MAX_PEERS`** en el MASTER destino como máximo de hotspots simultáneo ## Claves `SELF_SERVICE` -Misma semántica que **`adn-monitor.yaml`** / **`adn-proxy.yaml`** legado — tabla **`Clients`** compartida, flag **`modified`**, **RPTO** hacia el MASTER. +Misma semántica que **`adn-monitor.yaml`** — tabla **`Clients`** compartida, flag **`modified`**, **RPTO** hacia el MASTER. | Clave | Rol | |-------|-----| | **USE_SELFSERVICE** | Activa sincronización de opciones con MySQL (`true` / `false`). | | **DB_SERVER**, **DB_USERNAME**, **DB_PASSWORD**, **DB_NAME**, **DB_PORT** | Conexión MySQL. | -| **PBKDF2_SALT**, **PBKDF2_ITERATIONS** | Deben **coincidir** con monitor/backend para el hash de contraseñas. | +| **PBKDF2_SALT**, **PBKDF2_ITERATIONS** | Deben **coincidir** con **`adn-monitor.yaml`** para el hash de contraseñas. | Al arrancar el servidor registra **`(SELF_SERVICE) Database connection test: OK`** y **`(SELF_SERVICE) Enabled`** si el pool conecta. El self-service es **asíncrono**; el reenvío de voz no se bloquea por latencia de BD. @@ -106,15 +105,8 @@ Ver [Configuración — recarga en caliente](configuration.md#recarga-en-calient --- -## Proxy independiente (legado) - -El repo **adn-monitor** sigue incluyendo **`proxy/proxy.py`** para despliegues con relay UDP **separado** y **`adn-proxy.yaml`**. **No** ejecutes el proxy integrado y **`adn-proxy`** independiente en el mismo **`LISTEN_PORT`**. - ---- - ## Ver también - [Configuración](configuration.md) — referencia completa de **`adn-server.yaml`**. - [Monitorización e informes](monitoring.md) — informes TCP, panel, rotación de logs. - [Self-service](../../monitor/self-service.md) — **`Clients`**, temporización **RPTO**. -- [Proxy hotspot (independiente)](../../monitor/hotspot-proxy.md) — layout legado **`adn-proxy`**. diff --git a/docs/es/server/user-guide/introduction.md b/docs/es/server/user-guide/introduction.md index 5b8e64a..277a1db 100644 --- a/docs/es/server/user-guide/introduction.md +++ b/docs/es/server/user-guide/introduction.md @@ -27,7 +27,7 @@ Enrutado, temporizadores, control de bucle OpenBridge y manejo de protocolo est ## Programas relacionados - **Parrot / reproducción** — punto de entrada aparte (`adn-parrot.py`) para grabar y reproducir; ver [Parrot](parrot.md). -- **Proxy hotspot independiente** — **`adn-proxy`** legado en el repo **adn-monitor** si no usas el proxy integrado; ver [Proxy hotspot (independiente)](../../monitor/hotspot-proxy.md). +- **Proxy hotspot integrado** — `PROXY` en **`adn-server.yaml`**; ver [Proxy hotspot](hotspot-proxy.md). ## Siguientes pasos diff --git a/docs/es/server/user-guide/monitoring.md b/docs/es/server/user-guide/monitoring.md index 3c80e2c..f98500e 100644 --- a/docs/es/server/user-guide/monitoring.md +++ b/docs/es/server/user-guide/monitoring.md @@ -16,7 +16,7 @@ Las pilas antiguas (**legado** estilo `adn-dmr-server`) pueden **omitir** HELLO. 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). +**Pila completa:** [Descripción general del ADN Monitor](../../monitor/index.md) (monitor FastAPI, WebSocket, self-service). ### Líneas de log del canal de informes (logger `adn-monitor`) @@ -51,7 +51,6 @@ Estos procesos tratan **`SIGUSR2`** solo para **reabrir** los ficheros de log (` | Proceso | Claves típicas de configuración | |---------|-----------------------------------| | **`adn-server`** / **`adn-parrot`** | **`LOGGER.LOG_FILE`** (los logs del proxy integrado van al mismo fichero) | -| **`adn-proxy`** (independiente, legado) | **`LOG.PATH`** + **`LOG.LOG_FILE`** en `adn-proxy.yaml` — omitir si usas **`PROXY`** integrado en `adn-server.yaml` | | **`adn-monitor`** | **`LOG.PATH`** + **`LOG.LOG_FILE`** en `adn-monitor.yaml` | Ejemplo de fragmento en **`/etc/logrotate.d/adn`** (adaptar rutas y nombres de unidad): @@ -71,7 +70,7 @@ Ejemplo de fragmento en **`/etc/logrotate.d/adn`** (adaptar rutas y nombres de u } ``` -Repite **`postrotate`** con **`kill -USR2`** para **`adn-parrot`** y **`adn-monitor`** si rotas sus logs en el mismo host. Añade **`adn-proxy`** solo si sigues usando el proxy **independiente** (no hace falta con proxy integrado en **`adn-server`**). Usa el **PID** correcto (**`MainPID`** de systemd, pidfile, o el proceso que gestiones). +Repite **`postrotate`** con **`kill -USR2`** para **`adn-parrot`** y **`adn-monitor`** si rotas sus logs en el mismo host. Usa el **PID** correcto (**`MainPID`** de systemd, pidfile, o el proceso que gestiones). ## Requisitos @@ -82,4 +81,4 @@ Repite **`postrotate`** con **`kill -USR2`** para **`adn-parrot`** y **`adn-moni Los operadores que editan **opciones de dispositivo** desde el panel usan el flujo **self-service** (MySQL **`Clients`**, **RPTO** hacia el MASTER de conferencia). En despliegues actuales de **ADN DMR Peer Server** esto corre **dentro de `adn-server.py`**: configura **`SELF_SERVICE`** y **`PROXY`** en **`adn-server.yaml`** (ver [Proxy hotspot](hotspot-proxy.md)). Semántica del panel: [Self-service](../../monitor/self-service.md). -Los stacks legados pueden seguir usando **`adn-proxy`** independiente y **`adn-proxy.yaml`** — ver [Proxy hotspot (independiente)](../../monitor/hotspot-proxy.md). No ejecutes ambos en el mismo **`LISTEN_PORT`**. +Los logs del proxy hotspot forman parte de **`adn-server`** cuando **`PROXY`** está activo — ver [Proxy hotspot integrado](hotspot-proxy.md). diff --git a/docs/site-root-index.html b/docs/site-root-index.html new file mode 100644 index 0000000..875e96d --- /dev/null +++ b/docs/site-root-index.html @@ -0,0 +1,33 @@ + + + + + + ADN Systems documentation + + + + +

Redirecting… Español · English

+ +