Initial commit — DRB client (edge node) stack
Includes edge-node (FastAPI/MQTT/Discord voice), op25-container (SDR decoder), and icecast (audio streaming).
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# DRB Client (Edge Node)
|
||||
|
||||
The client-side stack for the Discord Radio Bot system. Runs on the SDR hardware machine. Decodes radio with OP25, streams audio via Icecast, and connects to the C2 server over MQTT.
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Description |
|
||||
|---|---|
|
||||
| `op25` | OP25 SDR decoder — tunes to radio systems and streams decoded audio |
|
||||
| `icecast` | Audio streaming server — receives audio from OP25 and serves it over HTTP |
|
||||
| `edge-node` | FastAPI node agent — bridges OP25 metadata, MQTT C2 commands, and Discord voice |
|
||||
|
||||
All services run with `network_mode: host` so they share the host network and can reach each other on localhost.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker + Docker Compose
|
||||
- An RTL-SDR or compatible SDR dongle connected to the host
|
||||
- Network access to the DRB server (C2 server)
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
# 1. Copy env file
|
||||
cp .env.example .env
|
||||
|
||||
# 2. Fill in .env
|
||||
# At minimum: NODE_ID, MQTT_BROKER (IP of the C2 server)
|
||||
|
||||
# 3. Build and start
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Environment Variables (`.env`)
|
||||
|
||||
| Variable | Description | Default |
|
||||
|---|---|---|
|
||||
| `NODE_ID` | Unique identifier for this node | required |
|
||||
| `NODE_NAME` | Human-readable name shown in the UI | `My Radio Node` |
|
||||
| `NODE_LAT` / `NODE_LON` | GPS coordinates for the map view | `0.0` |
|
||||
| `MQTT_BROKER` | IP or hostname of the C2 server | `localhost` |
|
||||
| `MQTT_PORT` | MQTT broker port | `1883` |
|
||||
| `C2_URL` | C2 server HTTP API URL (for audio uploads) | — |
|
||||
| `ICECAST_HOST` | Icecast hostname (leave as localhost) | `localhost` |
|
||||
| `ICECAST_PORT` | Icecast port | `8000` |
|
||||
| `ICECAST_MOUNT` | Icecast mount point | `/radio` |
|
||||
|
||||
## Node Provisioning Flow
|
||||
|
||||
1. Start the client stack — the edge node connects to MQTT and sends a **checkin**
|
||||
2. The C2 server registers the node as **pending approval**
|
||||
3. An admin approves the node in the web UI
|
||||
4. The admin assigns a **radio system** to the node via the UI
|
||||
5. The C2 server pushes the system config over MQTT
|
||||
6. The edge node writes the config and **starts OP25**
|
||||
7. OP25 begins decoding and streaming audio to Icecast
|
||||
|
||||
After a restart, OP25 resumes automatically if the node was already configured.
|
||||
|
||||
## Discord Voice
|
||||
|
||||
When a user runs `/join` in Discord (or clicks "Join Discord" in the UI), the C2 server sends a `discord_join` command to this node over MQTT. The edge node spins up a Discord bot using a token from the server's token pool and connects it to the requested voice channel, streaming live audio from Icecast.
|
||||
|
||||
## Logs
|
||||
|
||||
```bash
|
||||
docker compose logs -f edge-node
|
||||
docker compose logs -f op25
|
||||
docker compose logs -f icecast
|
||||
```
|
||||
Reference in New Issue
Block a user