Skip to content

sfowlr/RepeaterManager

Repository files navigation

RepeaterManager

A centralized management and monitoring system for DMR (Digital Mobile Radio) repeaters running MMDVMHost or HBlink. RepeaterManager aggregates real-time call logs and system status from multiple repeaters via MQTT, stores observations in a local SQLite database, and streams live updates to browser clients using Server-Sent Events (SSE).

Overview

RepeaterManager consists of three main components:

  1. mmdvmhost_logmon.py -- A log monitoring daemon that runs on each repeater. It parses MMDVMHost log output (from log files via pyinotify or from the systemd journal) and publishes structured JSON status messages to a central MQTT broker.

  2. repeater_manager.py -- The central aggregation server. It subscribes to MQTT topics from all repeaters, persists observations to a SQLite database, and fans out live data to connected browser clients.

  3. web_server.py -- An asyncio-based web server (using aiohttp) that serves a browser UI and streams real-time repeater status to clients via SSE.

Status

This project is an early prototype and work in progress. See the feature status below:

Feature Status
mmdvmhost_logmon log parsing and MQTT publishing Working
SSE fanout to browser clients Working
MQTT-based log transport Working
Call log / system log persistent storage Partial (~60%)
Web UI for historical and streaming data Partial (~10%)
Direct HBlink support (without MMDVMHost) Partial (~5%)
WebSocket fallback for browsers without SSE Not started
Raw TCP log transport Not started

Architecture

+------------------+      +------------------+
| Repeater 1       |      | Repeater 2       |
| (MMDVMHost)      |      | (MMDVMHost)      |
| mmdvmhost_logmon +----->| mmdvmhost_logmon |---+
+------------------+  |   +------------------+   |
                      |                           |
                      v                           v
               +------+------+    MQTT Broker     |
               | linux.spencerfowler.com          |
               +------+------+-------------------+
                      |
                      v
            +---------+---------+
            | repeater_manager  |
            | (MQTT subscriber) |
            +---+----------+----+
                |          |
                v          v
          +-----+---+  +--+--------+
          | localdb  |  | WebServer |
          | (SQLite) |  | (aiohttp) |
          +----------+  +--+--------+
                           |
                           v (SSE)
                     +-----------+
                     | Browser   |
                     | Clients   |
                     +-----------+

MQTT Topic Structure

Each repeater publishes to topics based on its repeater ID and timeslot:

  • <repeater_id>/info -- Repeater configuration and metadata (retained)
  • <repeater_id>/1 -- Timeslot 1 status updates
  • <repeater_id>/2 -- Timeslot 2 status updates

JSON Message Format

Idle state:

{"Status": "Idle"}

Active transmission:

{"Status": "TX", "Origin": "Net", "CallType": "Group", "Destination": "31131", "Source": "N4NQV", "Mode": "Voice"}

Transmission end (with statistics):

{"Status": "Idle", "Origin": "Net", "Loss": "0%", "CallType": "Group", "Destination": "31131", "Source": "N4NQV", "Length": "4.5s", "Mode": "Voice", "BER": "0.0%"}

Repeater info (published on startup):

{"RxFreq": "440000000", "TxFreq": "445000000", "Power": "50", "Latitude": "35.123", "Longitude": "-80.456", "Height": "100", "Location": "Somewhere, NC", "Callsign": "N4NQV", "ColorCode": "1", "Version": "1.5.2"}

Dependencies

Central Server (repeater_manager.py, web_server.py, localdb.py)

  • Python 3
  • paho-mqtt -- MQTT client library
  • aiohttp -- Async HTTP server framework
  • aiohttp-sse -- Server-Sent Events extension for aiohttp
  • SQLite 3 (included with Python)

Log Monitor (mmdvmhost_logmon.py)

  • Python 2 (uses Queue and cmp() which are Python 2 constructs)
  • paho-mqtt
  • One of the following for log source:
    • pyinotify -- For monitoring MMDVMHost log files on disk
    • python-systemd -- For reading from the systemd journal (used when pyinotify is not available)

Setup

1. Configure the MQTT Broker

An MQTT broker must be running and accessible to both the repeaters and the central server. The default broker address is linux.spencerfowler.com. To change this, edit the mqttc.connect() call in both mmdvmhost_logmon.py and repeater_manager.py.

2. Install Dependencies

Central server:

pip3 install paho-mqtt aiohttp aiohttp-sse

Log monitor (on each repeater):

pip install paho-mqtt pyinotify
# or, for systemd journal mode:
pip install paho-mqtt systemd-python

3. Deploy the Log Monitor on Each Repeater

Copy mmdvmhost_logmon.py to each repeater running MMDVMHost. The script reads the repeater ID from /etc/mmdvmhost.

File-based mode (using pyinotify):

python mmdvmhost_logmon.py /var/log/mmdvm/MMDVM-*.log

Systemd journal mode: If pyinotify is not installed, the script automatically falls back to reading from the systemd journal for the mmdvmhost.service unit.

python mmdvmhost_logmon.py

4. Start the Central Server

python3 repeater_manager.py

This starts:

  • An MQTT subscriber listening for repeater status on topics +/info, +/1, and +/2
  • A SQLite database (repeater_manager.db) for persisting observations
  • A web server on http://127.0.0.1:8080

5. Access the Web UI

Open a browser to http://127.0.0.1:8080. The page displays a live feed of repeater messages streamed via SSE.

Database Schema

The SQLite database (default_schema.sql) contains the following tables:

Table Purpose
Devices Registered repeater devices with metadata
Observations Individual log entries with timestamps, topics, and values
ObservationTypes Configurable topic-pattern matching rules for categorizing observations
RecordingSessions Tracks recording sessions with start/end timestamps

The database uses WAL (Write-Ahead Logging) mode for concurrent read/write access from the main thread and the background recording worker thread.

File Structure

RepeaterManager/
  repeater_manager.py     # Entry point: MQTT subscriber + web server orchestration
  web_server.py            # Async web server with SSE streaming
  localdb.py               # SQLite database wrapper with threaded write queue
  mmdvmhost_logmon.py      # MMDVMHost log parser and MQTT publisher (runs on repeaters)
  default_schema.sql       # SQLite schema for observation storage
  static/
    index.html             # Browser-based UI for viewing live repeater data
  LICENSE                  # GPLv3

Configuration

There are no configuration files. Key settings are currently hardcoded:

Setting Location Default
MQTT broker address repeater_manager.py:57, mmdvmhost_logmon.py:311 linux.spencerfowler.com
Web server host/port repeater_manager.py:62 127.0.0.1:8080
Database filename repeater_manager.py:59 repeater_manager.db
Record queue size localdb.py:18 500
MMDVMHost config path mmdvmhost_logmon.py:56 /etc/mmdvmhost

License

This project is licensed under the GNU General Public License v3.0. See LICENSE for details.

Copyright 2019 Spencer Fowler

About

Multi-repeater management/logging web server for MMDVMHost-based repeaters or HBlink-based servers

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors