Creating a P25 Capable Server for MMDVM Use

thisguyneedsabeer

Member
Premium Subscriber
Joined
May 20, 2020
Messages
94
I'm new to the Pi-Star world (awaiting account activation on the forums). I have a friend who is just outside of Simplex Range, and we have no digital repeaters in between us.

I purchased a pre-built MMDVM hotspot running Pi-Star for us both, and I was hoping that someone could check my proposed setup. I should note, that for now I do not want to use Brandmeister, I'd like to try to roll my own solution. I have 15 years in IT, 10 of which as a Systems Administrator so I feel like I can tackle this, so long as I understand the concepts.

Is this as simple as (and I doubt it is):

1. A Pi-Star MMDVM at each of our locations, this is what I bought: https://a.co/d/0a6JFk68
2. I program each of our radios (XTS5000) to the appropriate frequency of the hotspot
3. I install the P25 reflector software on a VPS or in my own home server farm: https://github.com/nostar/DVReflectors/tree/main / Ref: https://www.pistar.uk/new_ref_p25nxdn.php
4. Configure the talk group on my server side
5. Configure the P25 Hosts file on the hotspot with my TGID, IP, and Port that match my server settings
6. Configure the talk groups in the radio to be used on the hotspot channel. Ref:
7. We key up and talk to each other using P25 over the Internet via the hotspot. No physical P25 repeater required.

So my question is, what did I miss, how wrong is this, and if I am way off base, how can I accomplish what I'd like to do? Ultimately, I'd like to host a public server if possible for people to use via Brandmeister and give back to the community, but for now, I need to understand and develop the management concepts first before offering services out to a wider group of people.

I also want to note that because neither of us have any DMR/MotoTrbo capable devices at this time, I'd like to stick with P25 through Pi-Star until such a time when we can both procure a proper DMR HT.

TIA for any advice, and direction.
 

radioopperator

Member
Feed Provider
Joined
Apr 15, 2019
Messages
297
Just my two cents: You could of put a Allstar Pi at each end and a baby radio to each and went analog linking via internet / cellular.
that's an easy way to go linked analogue wise. Just had a cellular connected one drive from San Diego to Georgia and only had a few drop outs. You can do the MMDVM through several digital modes point to point two I'm told. I believe one MMDVM can be the server and you point all the slaves to its ip.
 

thisguyneedsabeer

Member
Premium Subscriber
Joined
May 20, 2020
Messages
94
I ended up getting this working, I was able to get my own Parrot at Reflector setup on a remote VPS, load the information into Pi-Star and have it successfully communicate between 2 Pi-Stars at separate locations. Currently this is all done over P25 as I do not have any DMR capable radios just yet, but will likely be picking up some basic Chinese ones soon to experiment with before purchasing commercial grade solutions.
 

kk6rq

Member
Joined
Feb 24, 2003
Messages
105
Location
Clear Lake, IA
You understand that Brandmeister has exactly zero to do with P25, right..?
You need to install DVSwitch server, then add P25Reflector, unless you plan on using someone else's reflector, in which case all you need is Pi-Star (sorry, it's late at night and it's TL;DR).
 
Last edited:

thisguyneedsabeer

Member
Premium Subscriber
Joined
May 20, 2020
Messages
94
You understand that Brandmeister has exactly zero to do with P25, right..?
You need to install DVSwitch server, then add P25Reflector, unless you plan on using someone else's reflector, in which case all you need is Pi-Star (sorry, it's late at night and it's TL;DR).
Yep, I figured all of that out. I was very new to the system when I posted this and thought everything Pi-Star went through Brandmeister, but that's just DMR coordination. My P25 setup is working without issue. I did not need to install a DVSwitch Server, just the P25Reflector and P25Parrot on my VPS, and then add my talkgroups to the radio and to the Pi-Star.

Tx/Rx no issue, Parrot is working as expected, all good here.
 

kk6rq

Member
Joined
Feb 24, 2003
Messages
105
Location
Clear Lake, IA
You understand that Brandmeister has exactly zero to do with P25, right..?

Yep, I figured all of that out. I was very new to the system when I posted this and thought everything Pi-Star went through Brandmeister, but that's just DMR coordination. My P25 setup is working without issue. I did not need to install a DVSwitch Server, just the P25Reflector and P25Parrot on my VPS, and then add my talkgroups to the radio and to the Pi-Star.

Tx/Rx no issue, Parrot is working as expected, all good here.
Alright, good to hear. Feel free to drop by and say hello on 11069 sometime. (Not listening 100% of the time so try again if I don't answer the 1st time)

-Bob
KK6RQ
 

thisguyneedsabeer

Member
Premium Subscriber
Joined
May 20, 2020
Messages
94
As soon as I get licensed I will, currently I can only listen to my licensed friends talk on my setup. Currently enrolled in a class that will run through September, and I'm hoping to take the test sometime in October when I have some free time.
 

capnjb

Newbie
Joined
Oct 13, 2005
Messages
1
I ended up getting this working, I was able to get my own Parrot at Reflector setup on a remote VPS, load the information into Pi-Star and have it successfully communicate between 2 Pi-Stars at separate locations. Currently this is all done over P25 as I do not have any DMR capable radios just yet, but will likely be picking up some basic Chinese ones soon to experiment with before purchasing commercial grade solutions.
How did you set this up on your VPS? I looked at the source on GitHub but don't know the procedure to set it up on my VPS.
 

kk6rq

Member
Joined
Feb 24, 2003
Messages
105
Location
Clear Lake, IA
I run it locally on a Pi 3B+. At some point I'll move it to the cloud.
You have to install DVSwitch server, then compile and add P25Reflector. In addition, if you plan on having a listed reflector, you have to request it from Jonathan/G4KLX's github page. If you're doing a private reflector, you just have to edit the P25HostsLocal.txt file on the pi-star client (or whatever they maybe be using, like Quantar-Bridge) of each user participating. If public/listed, you need to send him this info:

Ref# (pick an unused number)
IP address or host/domain
Port # (usually 41000)

If you do decide to do a private one, probably a good idea to let Jonathan know so he doesn't issue the number publicly to somebody else.
 
Last edited:

thisguyneedsabeer

Member
Premium Subscriber
Joined
May 20, 2020
Messages
94
How did you set this up on your VPS? I looked at the source on GitHub but don't know the procedure to set it up on my VPS.
1. Purchased a VPS, I personally use Hetzner as I have had great experience with them for over 10 years. I opted for a datacenter outside of the country, in this case Finland, in the event there are network disruptions in the US. The thought was I could switch my hotspot to mobile data and still get onto the talkgroups I programmed into my hotspot.

I'm currently paying 3.85EUR/mo ($4.25/mo) for 2vCPU. 2GB RAM, 40GB SSD, and have a 20TB bandwidth limit. PLENTY to run the required software.

Eventually I will be mirroring the setup on my home server for a local link, and likely picking up another VPS somewhere for a third layer of redundancy. Once everything gets registered to an FQDN via Cloudflare, high availability will be configured so if one node goes down, another node picks up.

2. Download, configure, and install the P25Parrot software:
Bash:
Clone the repository:
user@computer:/mnt/c/temp$ git clone https://github.com/g4klx/P25Clients.git
Cloning into 'P25Clients'...
remote: Enumerating objects: 3529, done.
remote: Counting objects: 100% (774/774), done.
remote: Compressing objects: 100% (277/277), done.
remote: Total 3529 (delta 637), reused 499 (delta 497), pack-reused 2755 (from 1)
Receiving objects: 100% (3529/3529), 3.06 MiB | 7.48 MiB/s, done.
Resolving deltas: 100% (2373/2373), done.

List the directory:
user@computer:/mnt/c/temp$ ls
P25Clients

Change directory into the newly download folder:
user@computer:/mnt/c/temp$ cd P25Clients/

List the directory:
user@computer:/mnt/c/temp/P25Clients$ ls
LICENCE  Makefile  P25Clients.sln  P25Gateway  P25Parrot  README.md

Change directory into the P25Parrot directory:
user@computer:/mnt/c/temp/P25Clients$ cd P25Parrot/

List the directory:
user@computer:/mnt/c/temp/P25Clients/P25Parrot$ ls
Makefile     P25Parrot.cpp      P25Parrot.vcxproj.filters  StopWatch.cpp  Thread.h   UDPSocket.cpp  prebuild.cmd
Network.cpp  P25Parrot.h        Parrot.cpp                 StopWatch.h    Timer.cpp  UDPSocket.h
Network.h    P25Parrot.vcxproj  Parrot.h                   Thread.cpp     Timer.h    Version.h

Execute the "make" command to build the file. Note: you may need to install some additional libraries to configure
your build environment within Linux. The terminal will inform you what packages may be required and they
can be installed with "apt" (assuming you are running a Debian based distribution).

Additionally, there isa "prebuild.cmd" which can be used to generate a Windows binary for use on a
non-Linux server.
user@computer:/mnt/c/temp/P25Clients/P25Parrot$ make
echo "const char *gitversion = \"72d92ee769c0c8ef43a5a73e8db003be48a44a4b\";" > GitVersion.h
c++ -g -O3 -Wall -std=c++0x -pthread -c -o Network.o Network.cpp
c++ -g -O3 -Wall -std=c++0x -pthread -c -o P25Parrot.o P25Parrot.cpp
c++ -g -O3 -Wall -std=c++0x -pthread -c -o Parrot.o Parrot.cpp
c++ -g -O3 -Wall -std=c++0x -pthread -c -o StopWatch.o StopWatch.cpp
c++ -g -O3 -Wall -std=c++0x -pthread -c -o Thread.o Thread.cpp
c++ -g -O3 -Wall -std=c++0x -pthread -c -o Timer.o Timer.cpp
c++ -g -O3 -Wall -std=c++0x -pthread -c -o UDPSocket.o UDPSocket.cpp
c++ Network.o P25Parrot.o Parrot.o StopWatch.o Thread.o Timer.o UDPSocket.o -g -O3 -Wall -std=c++0x -pthread -lpthread -o P25Parrot

List the directory and locate the newly created binary "P25Parrot":
user@computer:/mnt/c/temp/P25Clients/P25Parrot$ ls
GitVersion.h  Network.o      P25Parrot.o                Parrot.h       StopWatch.o  Timer.cpp      UDPSocket.h
Makefile      P25Parrot      P25Parrot.vcxproj          Parrot.o       Thread.cpp   Timer.h        UDPSocket.o
Network.cpp   P25Parrot.cpp  P25Parrot.vcxproj.filters  StopWatch.cpp  Thread.h     Timer.o        Version.h
Network.h     P25Parrot.h    Parrot.cpp                 StopWatch.h    Thread.o     UDPSocket.cpp  prebuild.cmd

Enable execution permissions on "P25Parrot" binary:
user@computer:/mnt/c/temp/P25Clients/P25Parrot$ chmod +x P25Parrot

Start the P25Parrot binary and bind it to UDP port 41001. You can pass any port you would like
here, in my experience with Pi-Star, UDP ports in the 41000-41010 range are already configured to
be open. You will also need to ensure your VPS is setup to allow UDP traffic inbound/outbound on
the designated port:
user@computer:/mnt/c/temp/P25Clients/P25Parrot$ ./P25Parrot 41001
Opening P25 network connection
Opening UDP port on 41001
Starting P25Parrot-20240129

3. I followed this YouTube video to learn how to manually add a talkgroup to Pi-Star:
. This video is 6-years old, but the content is still generally relevant.

4. Downloaded, configured, and installed the P25Reflector software: GitHub - nostar/DVReflectors: NXDN, P25, and YSF reflector software

Bash:
Clone the repository:
user@computer:/mnt/c/temp$ git clone https://github.com/nostar/DVReflectors
Cloning into 'DVReflectors'...
remote: Enumerating objects: 91, done.
remote: Counting objects: 100% (11/11), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 91 (delta 6), reused 5 (delta 5), pack-reused 80 (from 1)
Receiving objects: 100% (91/91), 1.02 MiB | 5.61 MiB/s, done.
Resolving deltas: 100% (44/44), done.

List the directory:
user@computer:/mnt/c/temp# ls
DVReflectors  P25Clients

Change directory into the newly downloaded folder:
user@computer:/mnt/c/temp$ cd DVReflectors/

List the directory:
user@computer:/mnt/c/temp/DVReflectors$ ls
LICENCE  NXDNReflector  P25Reflector  README.md  YSFReflector

Change directory into the P25Reflector directory:
user@computer:/mnt/c/temp/DVReflectors$ cd P25Reflector/

List the directory:
user@computer:/mnt/c/temp/DVReflectors/P25Reflector$ ls
Conf.cpp       Log.cpp    Network.cpp       P25Reflector.sh               Thread.cpp     UDPSocket.h
Conf.h         Log.h      Network.h         P25Reflector.vcxproj          Thread.h       Utils.cpp
DMRIds.dat     Makefile   P25Reflector.cpp  P25Reflector.vcxproj.filters  Timer.cpp      Utils.h
DMRLookup.cpp  Mutex.cpp  P25Reflector.h    StopWatch.cpp                 Timer.h        Version.h
DMRLookup.h    Mutex.h    P25Reflector.ini  StopWatch.h                   UDPSocket.cpp

Verify P25Reflector.ini matches the following:
user@computer:/mnt/c/temp/DVReflectors/P25Reflector$ nano P25Reflector.ini

[Output will be shown in a new screen]
[General]
Daemon=1

[Id Lookup]
Name=DMRIds.dat
Time=24

[Log]
# Logging levels, 0=No logging
DisplayLevel=1
FileLevel=1
FilePath=.
FileRoot=P25Reflector
FileRotate=1

[Network]
Port=41000
Debug=0

* Press CTRL+X to return to the terminal *

Execute the "make" command to build the file. Note: you may need to install some additional libraries to configure
your build environment within Linux. The terminal will inform you what packages may be required and they
can be installed with "apt" (assuming you are running a Debian based distribution).
user@computer:/mnt/c/temp/DVReflectors/P25Reflector$ make
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Conf.o Conf.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o DMRLookup.o DMRLookup.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Log.o Log.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Mutex.o Mutex.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Network.o Network.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o P25Reflector.o P25Reflector.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o StopWatch.o StopWatch.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Thread.o Thread.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Timer.o Timer.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o UDPSocket.o UDPSocket.cpp
c++ -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -c -o Utils.o Utils.cpp
c++ Conf.o DMRLookup.o Log.o Mutex.o Network.o P25Reflector.o StopWatch.o Thread.o Timer.o UDPSocket.o Utils.o -g -O3 -Wall -DHAVE_LOG_H -DUDP_SOCKET_MAX=2 -std=c++0x -pthread -lpthread -o P25Reflector

List the directory and locate the newly created binary "P25Gateway":
user@computer:/mnt/c/temp/DVReflectors/P25Reflector$ ls
Conf.cpp       Log.cpp    Network.cpp       P25Reflector.o                Thread.cpp     UDPSocket.h
Conf.h         Log.h      Network.h         P25Reflector.sh               Thread.h       UDPSocket.o
Conf.o         Log.o      Network.o         P25Reflector.vcxproj          Thread.o       Utils.cpp
DMRIds.dat     Makefile   P25Reflector      P25Reflector.vcxproj.filters  Timer.cpp      Utils.h
DMRLookup.cpp  Mutex.cpp  P25Reflector.cpp  StopWatch.cpp                 Timer.h        Utils.o
DMRLookup.h    Mutex.h    P25Reflector.h    StopWatch.h                   Timer.o        Version.h
DMRLookup.o    Mutex.o    P25Reflector.ini  StopWatch.o                   UDPSocket.cpp

Enable execution permissions on "P25Reflector" binary:
user@computer:/mnt/c/temp/DVReflectors/P25Reflector$ chmod +x P25Reflector

Start the reflector with the settings from the local P25Reflector.ini. You might need to elevate and execute the start command as the root user depending on your setup.
user@computer:/mnt/c/temp/DVReflectors/P25Reflector$ ./P25Reflector start /etc/P25Reflector.ini
I: 2024-08-19 14:32:32.941 Opening P25 network connection
I: 2024-08-19 14:32:32.941 Opening UDP port on 41000
I: 2024-08-19 14:32:32.941 Loaded 2 Ids to the callsign lookup table
M: 2024-08-19 14:32:32.941 Starting P25Reflector-20210912
I: 2024-08-19 14:32:32.941 Started the DMR Id lookup reload thread
M: 2024-08-19 14:32:36.109 Adding [Pi-Star-Name]     ([Remote-IP]:[Remote Port) <-- When a hotspot associates with your server, you will see it link here.

That's about as basic of a setup as you can get. I recommend using software like "screen" or "tmux" to run the software in the background. I personally use "screen."

To start a new screen and keep P25Parrot running:
  1. $ screen -d -m -s parrot
  2. $ screen -r parrot
  3. <navigate to the P25Parrot directory, and start the binary with the commands above>
  4. ctrl A+D to disconnect from the screen
To start a new screen and keep P25Reflector running:
  1. $ screen -d -m -s reflector
  2. $ screen -r reflector
  3. <navigate to the P25Reflector directory, and start the binary with the commands above>
  4. ctrl A+D to disconnect from the screen
I hope that helps point you in the right direction. I chose a Linux based setup, but both binaries will compile in a Windows environment and can be installed as services to run in the background with the right tools.

I run it locally on a Pi 3B+. At some point I'll move it to the cloud.
You have to install DVSwitch server, then compile and add P25Reflector. In addition, if you plan on having a listed reflector, you have to request it from Jonathan/G4KLX's github page. If you're doing a private reflector, you just have to edit the P25HostsLocal.txt file on the pi-star client (or whatever they maybe be using, like Quantar-Bridge) of each user participating. If public/listed, you need to send him this info:

Ref# (pick an unused number)
IP address or host/domain
Port # (usually 41000)

If you do decide to do a private one, probably a good idea to let Jonathan know so he doesn't issue the number publicly to somebody else.

This is all spot-on advice, I wanted my reflector to be as private as possible, so I chose an obscure number and just went with it. If it gets assigned I'll end up choosing a new one. I think the odds of my talkgroup ID number being used are pretty slim. If I'm not mistaken (and there's a good change I am) Motorola talkgroups can be 000000-999999 (maybe there's one less digit, I don't recall), but that should be 10^6 giving 1,000,000 distinct possibilities.
 
Top