5.2.3. RAYNET Private DMR

In order to learn more about how DMR works, I set about trying to implement my own server. I first looked at Brandmeister and Phoenix, could I download and run my own? No, they are closed systems.

Searching around I came across HBLink3. I found lots of references to it and even a few forks.

I quickly set up a simple bridge in a docker container, and was able to handle a conversation. I invited a few other people on play as well, and quickly discovered that all traffic was sent to all peers (Pi-stars) registered. This turns out to be by design. Multiple Talkgroups

With some simple changes I’ve been able to enable multiple talkgroups using HBLink as the foundation. Building and Running

I’ve built this using docker. HBLink does have a “Dockerfile” however the way it’s setup doesn’t work for me, as you have to have a separate repo to store the configurations. I’ve therefore created my own Dockerfile which builds a self contained image.

FROM debian:buster-slim

RUN apt-get update && apt-get install -y git python3-twisted python3-pip \
    python3-bitstring python3-autobahn python3-jinja2 libnet-ifconfig-wrapper-perl \
    procps wget && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*


ADD https://ham-digital.org/status/DMRIds.dat /opt

RUN pip3 install dmr_utils3 bitstring bitarray configparser

RUN git clone https://github.com/n0mjs710/HBlink3.git
RUN git clone https://github.com/sp2ong/HBmonitor.git

ADD entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

WORKDIR /opt/HBlink3
# copy config
COPY conf/* ./

COPY script/* ./

COPY monitor-config.py HBmonitor/config.py

RUN useradd -ms /bin/bash radio && \
    chown radio:radio /entrypoint.sh && \
    chown -R radio /opt

RUN mkdir -p /var/log/hblink/
RUN chown -R radio:radio /var/log/hblink

#USER radio
EXPOSE 62030/udp 62031/udp 42001/udp 8080 9000 8090

ENTRYPOINT [ "/entrypoint.sh" ]

The same container image is then run multiple times

  • HBlink
  • YSF Peer
  • Monitor

Depending on the entrypoint.sh script and command sent defines which function is run.

cd /opt/HBlink3
IPADDR="$(ifconfig eth0 |grep -A 1 'eth0' |tail -1 |cut -d 't' -f 2 |cut -d ' ' -f 2)"
sed -i -e "s/HOSTIP/$IPADDR/g" /opt/YSF2DMR.ini

case "$1" in
    python3 raynet.py
#    tail -F /opt/HBlink3/hblink.py
    cd /opt/hbmonitor3
    python3 monitor.py
    cd /opt/HBmonitor
    python3 monitor.py
    python3 playback.py
    wget 'https://ham-digital.org/status/DMRIds.dat' -O /opt/DMRIds.dat
    /opt/YSF2DMR /opt/YSF2DMR.ini
    echo $"Usage: $0 {blink|monitor|monitor3|playback|ysf2dmr}"
    exit 1
esac Management Portal

Allowing multiple talkgroups is just the start, next is to provide a management interface simalar to Brandmeister and others which will provide

  • Registration
  • Secure access
  • See talkgroups
  • Set and unset static Talkgroups
  • Define who can access which talkgroups
  • Monitor talkgroup activity

I plan to use Ruby on Rails to build this side, with either mysql or CockroachDB. Mysql is simple to run, but doesn’t scale too well. CockroachDB works well inside docker containers, and can scale very large if necessary. As this system will be queries for every conversation start it’s important that it responds quickly. Database design

class dmrids {
  String dmrid
  String callsign
  Integer userid

Class raynet_groups {
  String name
  String groupcode
  Integer number

Class static_groups {
  Integer user_id
  Integer talkgroup_id
  Boolean active

Class talkgroups {
  String name
  Integer number
  Boolean active
  Integer raynet_group_id

Class Users {
  String password
  Boolean active
  String firstname
  String surname
  String hotspotpassword
  String email
  String reset_password_token

Users --> dmrids
Users --> static_groups
raynet_groups --> Users
talkgroups <-- static_groups
raynet_groups --> talkgroups