You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

316 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# MQTT Support for DStarRepeater
DStarRepeater can optionally publish log messages and repeater status to
an MQTT broker, providing the same kind of live telemetry that MMDVMHost
offers. This makes it possible to monitor D-Star repeater activity from
dashboards, home-automation systems, or any MQTT client.
**MQTT support is entirely optional.** When built without the MQTT flag
the compiled binary is identical to the tree before MQTT was added — no
MQTT code is included and no additional libraries are required.
## Building
### Without MQTT (default)
```
make
```
Produces the same `dstarrepeaterd` as the original codebase. No
`libmosquitto` dependency.
### With MQTT
Install `libmosquitto-dev` first:
```
sudo apt-get install libmosquitto-dev
```
Then build with the `MQTT` flag:
```
make MQTT=1
```
This adds `-DMQTT` to the compiler flags and links against
`-lmosquitto`. All MQTT code paths are guarded by
`#if defined(MQTT)` / `#endif`, so the flag acts as a clean on/off
switch.
## Configuration
Add the following keys to your `dstarrepeater` configuration file
(the same flat key=value format used by all other settings):
```
mqttHost=127.0.0.1
mqttPort=1883
mqttAuth=0
mqttUsername=
mqttPassword=
mqttKeepalive=60
mqttName=dstar-repeater
```
| Key | Default | Description |
|-----------------|-------------------|----------------------------------------------------|
| `mqttHost` | `127.0.0.1` | MQTT broker hostname or IP address |
| `mqttPort` | `1883` | MQTT broker port |
| `mqttAuth` | `0` | Enable authentication (`0` = off, `1` = on) |
| `mqttUsername` | *(empty)* | Username when `mqttAuth=1` |
| `mqttPassword` | *(empty)* | Password when `mqttAuth=1` |
| `mqttKeepalive` | `60` | Keepalive interval in seconds |
| `mqttName` | `dstar-repeater` | Client name; also used as the MQTT topic prefix |
If `mqttHost` is left empty, MQTT is disabled at runtime even when
compiled in.
## MQTT Topics
All topics are automatically prefixed with the value of `mqttName`.
For example, with the default name `dstar-repeater`:
### `dstar-repeater/log`
Timestamped log messages, filtered by severity. The format matches the
log file output:
```
M: 2025-03-08 14:22:01: Starting D-Star Repeater - 20180403
M: 2025-03-08 14:22:01: Using wxWidgets 3.0.5 on Linux 6.1.21-v8+
M: 2025-03-08 14:22:01: Callsign set to "GB7XX B", gateway set to "GB7XX G"
M: 2025-03-08 14:22:01: Modem type set to "MMDVM"
I: 2025-03-08 14:22:01: MQTT connected to 127.0.0.1:1883 as dstar-repeater
M: 2025-03-08 14:22:01: Starting the D-Star repeater thread
M: 2025-03-08 14:22:01: Poll text set to "linux_mmdvm-20180403"
```
Log levels (highest to lowest):
| Letter | Level | Numeric |
|--------|---------------|---------|
| `F` | Fatal | 6 |
| `E` | Error | 5 |
| `W` | Warning | 4 |
| `I` | Info | 3 |
| `M` | Message | 2 |
| `D` | Debug | 1 |
Only messages at or above the configured threshold are published. The
default threshold is **2** (Message level), matching MMDVMHost behaviour.
### `dstar-repeater/status`
A JSON object published once per second with the current repeater state.
This is the D-Star equivalent of MMDVMHost's status output:
**Idle (no traffic):**
```json
{
"myCall1": "",
"myCall2": "",
"yourCall": "",
"rptCall1": "",
"rptCall2": "",
"tx": false,
"rxState": "listening",
"rptState": "listening",
"ber": 0.0,
"text": "",
"status1": "",
"status2": "",
"status3": "",
"status4": "",
"status5": ""
}
```
**During an RF transmission:**
```json
{
"myCall1": "MW0MWZ ",
"myCall2": " ",
"yourCall": "CQCQCQ ",
"rptCall1": "GB7XX B",
"rptCall2": "GB7XX G",
"tx": true,
"rxState": "process_data",
"rptState": "valid",
"ber": 1.3,
"text": "Hello from Pi-Star",
"status1": "",
"status2": "",
"status3": "",
"status4": "",
"status5": ""
}
```
**During a network (gateway) transmission:**
```json
{
"myCall1": "G4KLX ",
"myCall2": " ",
"yourCall": "GB7XX B",
"rptCall1": "GB7XX B",
"rptCall2": "GB7XX G",
"tx": true,
"rxState": "listening",
"rptState": "network",
"ber": 0.0,
"text": "",
"status1": "",
"status2": "",
"status3": "",
"status4": "",
"status5": ""
}
```
#### Status Field Reference
| Field | Type | Description |
|------------|---------|-----------------------------------------------------------|
| `myCall1` | string | Transmitting station's callsign (8 chars, space-padded) |
| `myCall2` | string | Transmitting station's short suffix (4 chars) |
| `yourCall` | string | Destination callsign (`CQCQCQ` for CQ calls) |
| `rptCall1` | string | Repeater callsign with module letter |
| `rptCall2` | string | Gateway callsign |
| `tx` | boolean | `true` when the repeater is transmitting |
| `rxState` | string | `listening`, `process_data`, or `process_slow_data` |
| `rptState` | string | See repeater states below |
| `ber` | float | Bit Error Rate as a percentage (0.0 when idle) |
| `text` | string | Slow-data text message (if any) |
| `status1``status5` | string | User-configured status text messages |
#### Repeater States (`rptState`)
| Value | Meaning |
|----------------|------------------------------------------------------|
| `listening` | Idle, waiting for traffic |
| `valid` | Receiving valid RF traffic |
| `valid_wait` | Valid RF transmission ended, waiting for ack window |
| `invalid` | Receiving RF traffic that failed validation |
| `invalid_wait` | Invalid RF ended, waiting |
| `timeout` | Transmission timed out |
| `timeout_wait` | Timeout ended, waiting |
| `network` | Receiving traffic from the gateway/network |
| `shutdown` | Repeater is shut down |
### `dstar-repeater/json`
Event-driven JSON messages published at D-Star state transitions, in the
format expected by [Display-Driver](https://github.com/MW0MWZ/Display-Driver).
This means DStarRepeater can drive an OLED/TFT display via MQTT with no
modifications to Display-Driver.
Unlike the `status` topic (polled once per second), the `json` topic only
publishes when something actually changes — a transmission starts, ends,
or is lost.
**RF transmission starts:**
```json
{"D-Star":{"action":"start","source_cs":"MW0MWZ ","source_ext":" ","destination_cs":"CQCQCQ ","reflector":"GB7XX G","source":"rf"}}
```
**Network transmission starts:**
```json
{"D-Star":{"action":"start","source_cs":"G4KLX ","source_ext":" ","destination_cs":"GB7XX B","reflector":"GB7XX G","source":"net"}}
```
**Transmission ends normally:**
```json
{"D-Star":{"action":"end"}}
```
**Transmission lost (watchdog timeout):**
```json
{"D-Star":{"action":"lost"}}
```
**Return to idle (sent after every end/lost):**
```json
{"MMDVM":{"mode":"idle"}}
```
**BER update (published once per second during active RF):**
```json
{"BER":{"mode":"D-Star","value":1.3}}
```
#### Display-Driver Compatibility
These messages use the exact same JSON keys and structure that
Display-Driver expects. If your `mqttName` is set to `dstar-repeater`,
configure Display-Driver to subscribe to `dstar-repeater/json`.
Display-Driver dispatches each top-level key to a specific parser:
| Top-level key | Display-Driver parser | When published |
|---------------|----------------------|------------------------------------------|
| `D-Star` | `parseDStar()` | Transmission start, end, or lost |
| `BER` | `parseBER()` | Once per second during active RF |
| `MMDVM` | `parseMMDVM()` | On return to idle |
## Subscribing to MQTT Output
Use any MQTT client to subscribe. For example, with `mosquitto_sub`:
```bash
# Follow all DStarRepeater topics:
mosquitto_sub -h 127.0.0.1 -t "dstar-repeater/#"
# Log messages only:
mosquitto_sub -h 127.0.0.1 -t "dstar-repeater/log"
# Status JSON only:
mosquitto_sub -h 127.0.0.1 -t "dstar-repeater/status"
# Display-Driver-compatible events:
mosquitto_sub -h 127.0.0.1 -t "dstar-repeater/json"
# Pretty-print status with jq:
mosquitto_sub -h 127.0.0.1 -t "dstar-repeater/status" | jq .
# Pretty-print Display-Driver events with jq:
mosquitto_sub -h 127.0.0.1 -t "dstar-repeater/json" | jq .
```
## Comparison with MMDVMHost
This implementation follows the same conventions as MMDVMHost's MQTT
support:
- Same `CMQTTConnection` class wrapping `libmosquitto`
- Same topic-prefix convention (`{name}/topic`)
- Same log-level filtering and format
- Same PID-based client ID scheme (avoids the `time_t` truncation
issue on 32-bit ARM)
- Same configuration key names (`mqttHost`, `mqttPort`, etc.)
- Same QoS default (EXACTLY_ONCE / QoS 2)
The key difference is that DStarRepeater is a **publish-only** client —
it does not subscribe to any MQTT topics or accept remote commands via
MQTT. The configuration file format also differs: DStarRepeater uses
flat `key=value` pairs rather than MMDVMHost's INI-style `[MQTT]`
section.
## Troubleshooting
**"Unable to start MQTT connection"** in logs:
- Check that Mosquitto (or another MQTT broker) is running on the
configured host and port
- Verify credentials if `mqttAuth=1`
- Check firewall rules if connecting to a remote broker
**No messages appearing:**
- Confirm the binary was built with `make MQTT=1`
- Check that `mqttHost` is not empty in the config file
- Verify the broker is accessible: `mosquitto_pub -h 127.0.0.1 -t test -m hello`
**Log messages missing but status works:**
- The log level threshold may be filtering them out. Lower-priority
messages (Debug, Trace) are not published by default.

Powered by TurnKey Linux.