|
|
# Configuration
|
|
|
|
|
|
## Files and workflow
|
|
|
|
|
|
| File | Committed | Role |
|
|
|
|------|-----------|------|
|
|
|
| `adn-server.example.yaml` | Yes | Template — copy to `adn-server.yaml` and edit. |
|
|
|
| `adn-server.yaml` | **No** (gitignored) | Main server: systems, globals, logging, aliases, reports. **Hot-reload** via `SIGHUP` (see [Configuration](configuration.md#hot-reload-adn-serveryaml)). |
|
|
|
| `adn-voice.example.yaml` | Yes | Template for voice — copy to `adn-voice.yaml`. |
|
|
|
| `adn-voice.yaml` | **No** (typical) | Voice/TTS/recording; merged into `config["VOICE"]` at startup and **hot-reloaded** (~every 15 s) if the file changes. |
|
|
|
|
|
|
Run:
|
|
|
|
|
|
```bash
|
|
|
python adn-server.py -c /path/to/adn-server.yaml
|
|
|
```
|
|
|
|
|
|
Optional: `--logging LEVEL` overrides `LOGGER.LOG_LEVEL`.
|
|
|
|
|
|
If `adn-voice.yaml` sits next to `adn-server.yaml`, it is loaded automatically. You can also put a `VOICE:` block inside `adn-server.yaml`; the separate file is the usual way to change announcements without touching the main config.
|
|
|
|
|
|
### Hot reload (`adn-server.yaml`)
|
|
|
|
|
|
After editing the main config you can reload **without restarting** the process (active voice streams on unchanged UDP listeners are preserved):
|
|
|
|
|
|
```bash
|
|
|
kill -HUP $(pidof adn-server.py) # or: systemctl reload adn-server
|
|
|
```
|
|
|
|
|
|
Example unit: **`examples/systemd/adn-server.service`** (copy to `/etc/systemd/system/`; includes `ExecReload` for `systemctl reload`).
|
|
|
|
|
|
**Reload applies:** `GLOBAL`, `REPORTS`, `ALIASES`, **`LOGGER.LOG_LEVEL`** (without process restart), **`PROXY`** (timeouts, debug, block lists — not bind or target), **`SELF_SERVICE`** (PBKDF2 flags merged; enabling/disabling DB loops needs restart), per-system settings, **new/removed SYSTEMS** (including `GENERATOR` expansion/collapse and new OpenBridge legs), and updated bind addresses (listener restart for that system only).
|
|
|
|
|
|
**Not reloaded:** **`DATABASE`** (MariaDB pool and `peer_dynamic_tgs` bootstrap), `adn-voice.yaml` (separate 15 s loop), Python code, subscriber alias files (separate periodic reload). **BRIDGES** table is not rebuilt on reload — restart if bridge rules changed in a way that requires a full reset. **`PROXY.LISTEN_PORT`**, **`LISTEN_IP`**, and **`TARGET_SYSTEM`** require a **full restart** to take effect.
|
|
|
|
|
|
**Secrets:** Never commit real passphrases, security URLs, or `user_passwords.json` / `encryption_key.secret`. Use placeholders in templates and keep production files local.
|
|
|
|
|
|
---
|
|
|
|
|
|
## Architecture: what is a “system”?
|
|
|
|
|
|
Each entry under **`SYSTEMS`** is a named **logical link** (UDP endpoint) that speaks **HBP** (HomeBrew Protocol) to hotspots/repeaters, or **OpenBridge** to other servers. Names are free-form strings (`SYSTEM`, `ECHO`, `OBP-UK`, …) and are used in logs and in the **bridge table** (`BRIDGES`) to identify where traffic enters or leaves.
|
|
|
|
|
|
Three **modes** exist:
|
|
|
|
|
|
| Mode | Typical use | Listens | Connects upstream |
|
|
|
|------|-------------|---------|-------------------|
|
|
|
| **MASTER** | Conference server for one or more hotspots/repeaters | **Yes** — `IP` / `PORT`, peers register with passphrase | No (peers connect to you) |
|
|
|
| **PEER** | Hotspot/repeater or service (e.g. echo) behaving as a **client** of a MASTER | **Yes** — local `IP` / `PORT` | **Yes** — `MASTER_IP` / `MASTER_PORT` must point at a MASTER |
|
|
|
| **OPENBRIDGE** | Link to another **server** over OpenBridge (DMRD v1 / DMRE) | **Yes** — `IP` / `PORT` | **Yes** — `TARGET_IP` / `TARGET_PORT` (peer server) |
|
|
|
|
|
|
**MASTER** holds the **`PEERS`** table at runtime (hotspots that authenticated). **PEER** maintains **STATS** (connection, pings). **OPENBRIDGE** uses **NETWORK_ID**, **PASSPHRASE**, **TARGET_***, **PROTO_VER** / **VER**, and optional **ENHANCED_OBP**, **RELAX_CHECKS**, **TGID_ACL**.
|
|
|
|
|
|
A single process can run **several** systems at once (e.g. one MASTER for users, one ECHO for playback, one OBP to a partner network).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `GLOBAL`
|
|
|
|
|
|
Server-wide defaults. Many keys can be overridden per system if `USE_ACL` (or similar) is set on that system.
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **PING_TIME** | Interval (seconds) for PEER keepalive / ping logic toward MASTER. |
|
|
|
| **MAX_MISSED** | How many missed pings before treating the PEER link as unhealthy (depends on implementation with STATS). |
|
|
|
| **USE_ACL** | If true, **REG_ACL**, **SUB_ACL**, **TGID_TS1_ACL**, **TGID_TS2_ACL** are applied (after processing into internal tuples). |
|
|
|
| **REG_ACL** | Access control for **registration** / peer IDs (`PERMIT:…` / `DENY:…`; see [ACL strings](#acl-strings)). |
|
|
|
| **SUB_ACL** | ACL for **subscriber** (radio) IDs on received traffic. |
|
|
|
| **TGID_TS1_ACL** | ACL for **talkgroup** on **timeslot 1**. |
|
|
|
| **TGID_TS2_ACL** | ACL for **talkgroup** on **timeslot 2**. |
|
|
|
| **GEN_STAT_BRIDGES** | If true, OpenBridge can trigger creation of **static** bridge rows for certain TGs (see [Bridges and talkgroups](bridges-and-talkgroups.md)). |
|
|
|
| **SERVER_ID** | Numeric server ID; stored as 4-byte value for OpenBridge / voice metadata. |
|
|
|
| **VALIDATE_SERVER_IDS** | If true (DMRE path), **source server** IDs may be checked against a downloaded list (`ALIASES` **SERVER_ID_**\*). |
|
|
|
| **URL_SECURITY** / **PORT_SECURITY** / **PASS_SECURITY** | If set, enables download of keys/password material from the security endpoint (see example comments). Empty = disabled. |
|
|
|
| **USERS_PASS** | Filename for per-radio password JSON (optional). |
|
|
|
| **HASH_ENCRYPT** | Path to encryption key for password file handling. |
|
|
|
|
|
|
### Talker Alias (`GLOBAL`)
|
|
|
|
|
|
Optional DMR Talker Alias on HBP (`DMRA` packets). Full guide: [Talker Alias](talker-alias.md).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **TALKER_ALIAS** | Enable server TA inject/passthrough (`false` default). |
|
|
|
| **TALKER_ALIAS_MODE** | `both` (default), `passthrough`, or `inject`. |
|
|
|
| **TALKER_ALIAS_FORMAT** | Template, e.g. `{callsign} {fname}`. Max **29** chars (protocol limit, not YAML). |
|
|
|
| **TALKER_ALIAS_SEND_DMRA** | Send standalone HBP `DMRA` UDP (`false` default; radios use embedded LC). |
|
|
|
| **TALKER_ALIAS_TEXT_FORMAT** | `utf8`, `iso8`, `7bit`, or comma list (e.g. `utf8,iso8` for Motorola + Hytera). Default `utf8`. |
|
|
|
|
|
|
---
|
|
|
|
|
|
## `SYSTEMS` — common fields
|
|
|
|
|
|
These appear mainly on **MASTER** (and often on **PEER**). OpenBridge uses a different subset.
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **MODE** | `MASTER`, `PEER`, or `OPENBRIDGE`. |
|
|
|
| **ENABLED** | If `false`, the system is skipped. |
|
|
|
| **IP** / **PORT** | UDP bind address for this system’s HBP or OpenBridge listener. |
|
|
|
| **PASSPHRASE** | Shared secret for HBP authentication (MASTER ↔ PEER). Must match between a PEER and its MASTER. |
|
|
|
| **USE_ACL** | Per-system ACL override when true (uses system-level `REG_ACL` / `SUB_ACL` / `TGID_TS*_ACL`). |
|
|
|
| **GROUP_HANGTIME** | Hang time (seconds) for group voice state. |
|
|
|
| **DEFAULT_UA_TIMER** | Default timeout (minutes in many places) for **user-activated** bridges. |
|
|
|
| **ANNOUNCEMENT_LANGUAGE** | Default language folder under `Audio/<lang>/` for prompts on this system. |
|
|
|
| **ALLOW_UNREG_ID** | Whether unregistered subscriber IDs are allowed (MASTER). |
|
|
|
|
|
|
---
|
|
|
|
|
|
## `SYSTEMS` — MASTER
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **REPEAT** | If true, received traffic can be **repeated** to other connected peers on the MASTER (typical conference behaviour). |
|
|
|
| **MAX_PEERS** | Maximum connected hotspots. On the **proxy target** MASTER, caps concurrent fan-in sessions. |
|
|
|
| **EXPORT_AMBE** | Feature flag for AMBE export (if enabled in build). |
|
|
|
| **SINGLE_MODE** | Affects OPTIONS / generator expansion (single-user style). |
|
|
|
| **VOICE_IDENT** | Enables periodic **voice ident** when conditions are met (see `IdentUseCases`). |
|
|
|
| **TS1_STATIC** / **TS2_STATIC** | Comma-separated static TG lists pushed via OPTIONS handling (see `options_config`). |
|
|
|
| **DEFAULT_REFLECTOR** | Default **reflector** number for `#` dial bridges (0 = none). |
|
|
|
| **OVERRIDE_IDENT_TG** | Optional TG for voice ident instead of all-call. |
|
|
|
| **GENERATOR** | If **> 1**, this MASTER is expanded into **`NAME-0`**, **`NAME-1`**, … with consecutive ports (see `expand_generator` in code). Legacy standalone **`adn-proxy`** used the same range; the **integrated** proxy instead uses **inject-only** **`PROXY.TARGET_SYSTEM`** (no per-hotspot UDP ports on the server). |
|
|
|
|
|
|
**MASTER** listens for PEER connections (unless it is the **inject-only** proxy target — see [Hotspot proxy](hotspot-proxy.md)); each authenticated peer is stored under **`PEERS`** at runtime.
|
|
|
|
|
|
---
|
|
|
|
|
|
## `SYSTEMS` — PEER
|
|
|
|
|
|
A **PEER** connects **outbound** to a **MASTER** and listens locally for the radio or app.
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **MASTER_IP** / **MASTER_PORT** | Address of the **MASTER** to register with (must match that MASTER’s `IP`/`PORT`). |
|
|
|
| **RADIO_ID** | This peer’s ID in HBP (4-byte). |
|
|
|
| **CALLSIGN**, **RX_FREQ**, **TX_FREQ**, **COLORCODE**, **LATITUDE**, … | RPT payload fields sent to the MASTER during registration (fixed widths in protocol). |
|
|
|
| **OPTIONS** | Byte string / options line (e.g. `TS2=9990;`) for static TG / behaviour. |
|
|
|
| **LOOSE** | Relaxed handling flag where applicable. |
|
|
|
|
|
|
The **echo** example (`adn-echo.example.yaml`) is a PEER that attaches to the **ECHO** MASTER: same **PASSPHRASE**, **MASTER_PORT** = ECHO’s **PORT**. See [Echo](echo.md).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `SYSTEMS` — OPENBRIDGE
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **NETWORK_ID** | Must match the peer’s **NETWORK_ID** in OpenBridge packets. |
|
|
|
| **TARGET_IP** / **TARGET_PORT** | Remote OpenBridge peer (UDP). |
|
|
|
| **TGID_ACL** (or **TG1_ACL**) | Talkgroup ACL for OpenBridge (often `DENY:0-82,…` style ranges). |
|
|
|
| **RELAX_CHECKS** | Allow packets when peer socket does not match `TARGET` strictly (use with care). |
|
|
|
| **ENHANCED_OBP** | Enables **BCSQ** / **BCKA** and multi-path loop control — **should be `true`** for ADN Systems inter-server links (see below). |
|
|
|
| **PROTO_VER** | Embedded **DMRE** protocol version; **`5`** selects **DMRE / OpenBridge v5** (89-byte frame, BLAKE2b). Default in code is **5**; use **5** for new ADN deployments. |
|
|
|
|
|
|
**ADN Systems recommendation:** For every OpenBridge peer in the ADN mesh, set **`PROTO_VER: 5`** (DMRE v5) and **`ENHANCED_OBP: true`**. Align the same settings on **both** ends. Older **DMRD v1**-only peers are possible for backward compatibility but are not the recommended mode for the network.
|
|
|
|
|
|
Ingress filters and loop control: [OpenBridge protocol](../protocols/openbridge.md) (including [DMRE vs OpenBridge v5](../protocols/openbridge.md#dmre-and-openbridge-v5)) and [Special numbers — OpenBridge ingress](special-numbers.md#openbridge-ingress--group-tg-filters).
|
|
|
|
|
|
Inbound UDP for all OPENBRIDGE systems can use the shared **`OBP_PROXY`** fan-in (standard port **62032**). See [OBP proxy](obp-proxy.md).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `OBP_PROXY` (integrated OpenBridge fan-in)
|
|
|
|
|
|
Active when **`OBP_PROXY`** is present or when any **OPENBRIDGE** system exists (defaults apply). All OpenBridge inbound UDP is demuxed on **`LISTEN_PORT`** (default **62032**); per-bridge legacy listeners are optional. Full guide: [OBP proxy](obp-proxy.md).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **LISTEN_PORT** / **LISTEN_IP** | UDP bind for OpenBridge fan-in (pair to hotspot **`PROXY`** **62031**). |
|
|
|
| **BIND_LEGACY_PORTS** | When `true`, also listen each **`SYSTEMS.*.PORT`** that differs from **`LISTEN_PORT`** (per-bridge migration). |
|
|
|
| **ENABLED** | Set `false` to restore per-bridge UDP bind (legacy mode). |
|
|
|
|
|
|
---
|
|
|
|
|
|
## `BRIDGES` (runtime)
|
|
|
|
|
|
The **bridge table** maps TG keys to routing rows. It is **in memory** for the running process.
|
|
|
|
|
|
The YAML loader does **not** load a top-level `BRIDGES:` block from `adn-server.yaml` into the router today — initial rows are created in code (e.g. **9990 / ECHO** bootstrap when an **ECHO** system exists), then **OPTIONS**, **user-activated** bridges, **static** bridges, and **OpenBridge** logic add rows over time.
|
|
|
|
|
|
For the conceptual model (ACTIVE, TS, TGID, timeouts): [Bridges and talkgroups](bridges-and-talkgroups.md).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `REPORTS`
|
|
|
|
|
|
TCP report channel for **adn-monitor** (or compatible dashboards). **adn-server 2.x** speaks **report v2** only; legacy dashboards that expect **v1** need the optional [report-proxy](report-proxy.md) (separate package).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **REPORT** | Enable/disable sending. |
|
|
|
| **REPORT_INTERVAL** | Periodic push interval (seconds). |
|
|
|
| **REPORT_PORT** | Local port the **server listens on** for report clients. |
|
|
|
| **REPORT_CLIENTS** | Comma-separated or list of allowed client IPs (see example). |
|
|
|
|
|
|
Details: [Monitoring and reports](monitoring.md). Legacy v1 monitors: [Report proxy](report-proxy.md).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `PROXY` (integrated hotspot proxy)
|
|
|
|
|
|
Always started when a **`PROXY`** block is present (see `adn-server.example.yaml`). Hotspots connect to **`LISTEN_PORT`**; traffic is injected into **`TARGET_SYSTEM`**. Full guide: [Hotspot proxy](hotspot-proxy.md).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **LISTEN_PORT** / **LISTEN_IP** | UDP bind for hotspot connections. |
|
|
|
| **TARGET_SYSTEM** | **MASTER** system name receiving injected HBP. That system becomes **inject-only** (`IP` / `PORT` removed at load). |
|
|
|
| **TIMEOUT** | Session idle timeout (seconds). |
|
|
|
| **DEBUG** / **CLIENT_INFO** | Logging verbosity. |
|
|
|
| **BLACK_LIST** / **IP_BLACK_LIST** | Block radio IDs or client IPs. |
|
|
|
|
|
|
Do **not** run standalone **`adn-proxy`** on the same **`LISTEN_PORT`** when the integrated proxy is enabled.
|
|
|
|
|
|
---
|
|
|
|
|
|
## `DATABASE` (MariaDB)
|
|
|
|
|
|
**Required** for typical conference-server configs: any deployment with **`PROXY`**, or at least one **`MASTER`** / **`OPENBRIDGE`** system. **Not** required for minimal **echo-only** PEER fleets (`adn-server.py --echo`).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **DB_SERVER** | MariaDB/MySQL host. |
|
|
|
| **DB_USERNAME** / **DB_PASSWORD** | Credentials. |
|
|
|
| **DB_NAME** | Database name (often the same as **adn-monitor**, e.g. `hbmon`). |
|
|
|
| **DB_PORT** | TCP port (default **3306**). |
|
|
|
|
|
|
**Uses one shared connection pool** for:
|
|
|
|
|
|
- **Dynamic TG persistence** — table **`peer_dynamic_tgs`** (per-peer user-activated TGs across hotspot reconnects). The server **creates the table on startup** if missing (migration id **`004_peer_dynamic_tgs`**, same schema as adn-monitor).
|
|
|
- **Integrated self-service** — table **`Clients`** when **`SELF_SERVICE.USE_SELFSERVICE: true`**.
|
|
|
|
|
|
Startup aborts with a clear log if MariaDB is unreachable or **`DATABASE`** is incomplete. Install **`mysqlclient`** (`pip install -e ".[selfservice]"` includes it).
|
|
|
|
|
|
**Hot reload:** changing **`DATABASE`** requires a **full process restart**.
|
|
|
|
|
|
Details: [Bridges and talkgroups — dynamic TG persistence](bridges-and-talkgroups.md#dynamic-tg-persistence-mariadb).
|
|
|
|
|
|
---
|
|
|
|
|
|
## `SELF_SERVICE` (MySQL / dashboard options)
|
|
|
|
|
|
Optional; requires `pip install -e ".[selfservice]"` when **`USE_SELFSERVICE: true`**. Uses the **`DATABASE`** block above (not separate DB keys in **`SELF_SERVICE`**). PBKDF2 parameters must **match** **adn-monitor**. See [Self-service](../../monitor/self-service.md) and [Hotspot proxy](hotspot-proxy.md#self_service-keys).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **USE_SELFSERVICE** | Enable MySQL-backed options sync from the dashboard (`true` / `false`). |
|
|
|
| **PBKDF2_SALT** / **PBKDF2_ITERATIONS** | Must match **`adn-monitor.yaml`** / password tooling. |
|
|
|
|
|
|
---
|
|
|
|
|
|
## `LOGGER`
|
|
|
|
|
|
Implemented in `infrastructure/logging_config.py` (`setup_logging`). Values are read from the **`LOGGER`** block (or overridden by `--logging` for **LOG_LEVEL** only).
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **ENABLED** | **`true`** (default when omitted) — normal logging. **`false`** — disable application log output (no console or file handlers; `NullHandler` only). Legacy configs without this key behave as today. |
|
|
|
| **LOG_HANDLERS** | Comma-separated list of handler **tokens** (whitespace around commas is fine). Each token selects outputs; you can combine several. Recognised values: **`console-timed`** or **`console`** — log to **stderr** with format `LEVEL asctime message`; **`file-timed`** or **`file`** — log to **LOG_FILE** with the same format (UTF-8). **Default** if omitted: `console-timed`. Examples: `console-timed` only; `file-timed` only; `console-timed,file-timed` for both console and file. |
|
|
|
| **LOG_FILE** | Path used when **`file-timed`** or **`file`** is in **LOG_HANDLERS**. If missing, the code defaults to `/dev/null`. If the path is **`/dev/null`**, file handlers are **not** attached even if listed. If the file cannot be opened (permissions, missing directory), a warning is written to stderr and logging continues without that file handler. |
|
|
|
| **LOG_LEVEL** | Root logger level: **`DEBUG`**, **`INFO`**, **`WARNING`**, **`ERROR`**, **`CRITICAL`** (case-insensitive; default **INFO**). Unknown names fall back to **INFO**. You can override at startup with **`python adn-server.py --logging LEVEL`** (same names). A custom **`TRACE`** level is registered for occasional `logger.trace(...)` calls; use **`DEBUG`** for verbose diagnostics in normal operation. |
|
|
|
| **LOG_NAME** | Name of the logger returned to the application (default **`ADN`**). Does not change the list of handlers; it selects which named logger gets the configured level. |
|
|
|
|
|
|
---
|
|
|
|
|
|
## `ALIASES`
|
|
|
|
|
|
Downloads and local files for **peer IDs**, **subscriber IDs**, **talkgroup labels**, optional **server ID list**, **checksums**, and **keys**. Used for dashboards, validation, and optional security downloads.
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|-----|---------|
|
|
|
| **PATH** | Base directory for JSON/TSV/pickle files. |
|
|
|
| **TRY_DOWNLOAD** | Whether to fetch from URLs when stale. |
|
|
|
| **PEER_FILE** / **SUBSCRIBER_FILE** / **TGID_FILE** | Local filenames. |
|
|
|
| **\*_URL** | Remote sources for downloads. |
|
|
|
| **SUB_MAP_FILE** | Pickle path for **SUB_MAP** (private call routing); default name if empty. |
|
|
|
| **STALE_DAYS** | Refresh threshold for downloads. |
|
|
|
|
|
|
---
|
|
|
|
|
|
## `VOICE` (from `adn-voice.yaml` or inline)
|
|
|
|
|
|
Merged into `config["VOICE"]`. See [Voice, announcements, and TTS](voice-and-tts.md) and `adn-voice.example.yaml`.
|
|
|
|
|
|
---
|
|
|
|
|
|
## ACL strings
|
|
|
|
|
|
Processed by `acl_build`: `PERMIT:` or `DENY:` followed by comma-separated IDs or ranges.
|
|
|
|
|
|
Examples:
|
|
|
|
|
|
- `PERMIT:ALL` — allow all IDs in range.
|
|
|
- `DENY:1` — deny ID 1 only.
|
|
|
- `DENY:0-82,9990-9999` — deny listed ranges.
|
|
|
|
|
|
Global ACLs apply when `USE_ACL` is true; OpenBridge may use **TGID_ACL** on the OBP system.
|
|
|
|
|
|
---
|
|
|
|
|
|
## Python environment
|
|
|
|
|
|
Use the project interpreter (see workspace rules), e.g. `python3.11` from pyenv, for consistent behaviour with production.
|
|
|
|
|
|
---
|
|
|
|
|
|
## See also
|
|
|
|
|
|
- [Introduction](introduction.md) — role of the server.
|
|
|
- [Bridges and talkgroups](bridges-and-talkgroups.md) — `BRIDGES` semantics.
|
|
|
- [Special numbers](special-numbers.md) — reserved TGs and server IDs.
|
|
|
- [Echo](echo.md) — PEER example (echo process).
|
|
|
- [Hotspot proxy](hotspot-proxy.md) — integrated **`PROXY`** / **`SELF_SERVICE`**.
|
|
|
- [OBP proxy](obp-proxy.md) — integrated **`OBP_PROXY`** OpenBridge fan-in.
|