Created
February 11, 2025 15:34
-
-
Save wd5gnr/62bce94b7097414d094d1e81bf46cfe2 to your computer and use it in GitHub Desktop.
Revisions
-
wd5gnr created this gist
Feb 11, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,26 @@ You need to do the following: 1. Copy pistar-remote.wd5gnr to /usr/local/sbin/pistar-remote.wd5gnr AND /usr/local/sbin/pistar-remote.wd5gnr.backup (important!) 1. Copy the files (remote-user-hook-example0, bm_tg.py, gnrcheck) for /usr/local/bin to your /usr/local/bin directory 1. Edit (don't copy) your /etc/pistar-remote to look like the one below 1. Copy and Edit /home/pi-star/user-hook-data to fit your needs 1. Make all the files except user-hook-data executable (e.g., chmod +x gnrcheck) # Commands Assuming you set the prefix to 77: * 7700002 - Deletes static talkgroup #2 (slot 1; as defined in user-hook-data * 7710002 - Adds static talkgroup #2 (slot 1) * 7720003 - Disables DMR network #3 * 7730003 - Enables DMR network #3 # Reinstalling Every time WPSD updates, this script will end. Run gnrcheck to fix things. It will tell you if you need to fix it and then will show you the instructions to fix it. However, if you run `gnrcheck fix` it will try to fix things for you as long as the .wd5gnr and the .wd5gnr.backup files match. # TODO Right now, this only works for DMR but it is easy to add the other modes which I will be doing shortly. This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,31 @@ # This wouldn't exist if/when this feature is pulled into mainstream #!/bin/bash DIR=/usr/local/sbin FBASE=pistar-remote echo Checking gnrcmd setup if diff "$DIR/$FBASE" "$DIR/$FBASE.wd5gnr" >/dev/null then echo GNR is present exit 0 fi echo GNR not present if diff "$DIR/$FBASE" "$DIR/$FBASE.original" >/dev/null then echo No changes detected on original if ! diff "$DIR/$FBASE.wd5gnr" "$DIR/$FBASE.wd5gnr.backup" >/dev/null then echo Warning: Backup is not the same! echo Resolve this before relinking exit 1 fi if [ "$1" == "fix" ] then echo Fixing ln -sf "$DIR/$FBASE.wd5gnr" "$DIR/$FBASE" sudo systemctl restart pistar-remote exit 0 fi echo issue: ln -sf \"$DIR/$FBASE.wd5gnr\" \"$DIR/$FBASE\" echo then: systemctl restart pistar-remote fi exit 1 This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,56 @@ # NOTE: You only need to change what's in [enable] to suit your purpose [banner] # Pi-Star Remote config file # This config file is desiged for the Pi-Star Keeper remote control # The remote control system is designed to give repeater keepers an # RF KillSwitch for their repeaters. [enable] # Is the Pi-Star Remote Enabled? (true|false) enabled=true local_prefix=77 local_script=/usr/local/bin/remote-user-hook-example0 scan_rate=15 # scan_rate is how many seconds between looking for commands (default was 30) [keeper] # Keepers Information callsign=WD5GNR [d-star] # UR fields #svckill=SVCKILL #svcrestart=SVCRSTRT #reboot=REBOOTPI #shutdown=SHUTDOWN #8Ball=8BALL [dmr] # TG commands svckill=7999999 svcrestart=7999998 reboot=7999997 shutdown=7999996 gnrcmd=77 [ysf] # ROOM commands #svckill=99999 #svcrestart=99998 #reboot=99997 #shutdown=99996 [p25] # P25 Talkgroups are limited to 1->65535 #svckill=65531 #svcrestart=65532 #reboot=65533 #shutdown=65534 [m17] # M17 destination fields #svckill=SVCKILL #svcrestart=SVCRSTRT #reboot=REBOOTPI #shutdown=SHUTDOWN This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,515 @@ #!/usr/bin/python ########################################################################### # # # WPSD RF Remote Control # # # # Refactored for Py3 - W0CHP # # # ########################################################################### # WD5GNR version import datetime import time import linecache import os import subprocess import configparser import random import re # Read the config; config = configparser.RawConfigParser() config.read('/etc/pistar-remote') # Read the MMDVMHost config; mmdvmConfig = configparser.RawConfigParser() mmdvmConfig.read('/etc/mmdvmhost') # Read the YSFGateway config; ysfGatewayConfig = configparser.RawConfigParser() ysfGatewayConfig.read('/etc/ysfgateway') # If not enabled, die; isEnabled = config.get('enable', 'enabled') if (isEnabled != 'true'): quit() # Substitute variables from config mmdvmLogPath = mmdvmConfig.get('Log', 'FilePath') mmdvmFileRoot = mmdvmConfig.get('Log', 'FileRoot') ysfGatewayLogPath = ysfGatewayConfig.get('Log', 'FilePath') ysfGatewayFileRoot = ysfGatewayConfig.get('Log', 'FileRoot') keeperCall = config.get('keeper', 'callsign') local_prefix=config.get('enable','local_prefix',fallback='999999999999') local_script=config.get('enable','local_script',fallback='') scan_rate=config.getint('enable','scan_rate',fallback=30) # DMR Control Options if config.has_option('dmr', 'svckill'): dmrstop = config.get('dmr', 'svckill') else: dmrstop = str(999999999999) if config.has_option('dmr', 'svcrestart'): dmrrestart = config.get('dmr', 'svcrestart') else: dmrrestart = str(999999999999) if config.has_option('dmr', 'reboot'): dmrreboot = config.get('dmr', 'reboot') else: dmrreboot = str(999999999999) if config.has_option('dmr', 'shutdown'): dmrshutdown = config.get('dmr', 'shutdown') else: dmrshutdown = str(999999999999) if config.has_option('dmr', 'hostfiles'): dmrhostfiles = config.get('dmr', 'hostfiles') else: dmrhostfiles = str(999999999999) if config.has_option('dmr', 'reconnect'): dmrreconnect = config.get('dmr', 'reconnect') else: dmrreconnect = str(999999999999) # D-Star Control Options if config.has_option('d-star', 'svckill'): dstarstop = config.get('d-star', 'svckill') else: dstarstop = str(999999999999) if config.has_option('d-star', 'svcrestart'): dstarrestart = config.get('d-star', 'svcrestart') else: dstarrestart = str(999999999999) if config.has_option('d-star', 'reboot'): dstarreboot = config.get('d-star', 'reboot') else: dstarreboot = str(999999999999) if config.has_option('d-star', 'shutdown'): dstarshutdown = config.get('d-star', 'shutdown') else: dstarshutdown = str(999999999999) if config.has_option('d-star', 'hostfiles'): dstarhostfiles = config.get('d-star', 'hostfiles') else: dstarhostfiles = str(999999999999) if config.has_option('d-star', 'getip'): dstargetip = config.get('d-star', 'getip') else: dstargetip = str(999999999999) if config.has_option('d-star', 'wifissid'): dstargetwifissid = config.get('d-star', 'wifissid') else: dstargetwifissid = str(999999999999) if config.has_option('d-star', 'wifirssi'): dstargetwifirssi = config.get('d-star', 'wifirssi') else: dstargetwifirssi = str(999999999999) if config.has_option('d-star', '8Ball'): dstar8ball = config.get('d-star', '8Ball') else: dstar8ball = str(999999999999) dstarmodule = mmdvmConfig.get('General', 'Callsign').ljust( 7) + mmdvmConfig.get('D-Star', 'Module') # YSF Control Options if config.has_option('ysf', 'svckill'): ysfstop = config.get('ysf', 'svckill') else: ysfstop = str(999999999999) if config.has_option('ysf', 'svcrestart'): ysfrestart = config.get('ysf', 'svcrestart') else: ysfrestart = str(999999999999) if config.has_option('ysf', 'reboot'): ysfreboot = config.get('ysf', 'reboot') else: ysfreboot = str(999999999999) if config.has_option('ysf', 'shutdown'): ysfshutdown = config.get('ysf', 'shutdown') else: ysfshutdown = str(999999999999) if config.has_option('ysf', 'hostfiles'): ysfhostfiles = config.get('ysf', 'hostfiles') else: ysfhostfiles = str(999999999999) # P25 Control Options if config.has_option('p25', 'svckill'): p25stop = config.get('p25', 'svckill') else: p25stop = str(999999999999) if config.has_option('p25', 'svcrestart'): p25restart = config.get('p25', 'svcrestart') else: p25restart = str(999999999999) if config.has_option('p25', 'reboot'): p25reboot = config.get('p25', 'reboot') else: p25reboot = str(999999999999) if config.has_option('p25', 'shutdown'): p25shutdown = config.get('p25', 'shutdown') else: p25shutdown = str(999999999999) if config.has_option('p25', 'hostfiles'): p25hostfiles = config.get('p25', 'hostfiles') else: p25hostfiles = str(999999999999) # M17 Control Options if config.has_option('m17', 'svckill'): m17stop = config.get('m17', 'svckill') else: m17stop = str(999999999999) if config.has_option('m17', 'svcrestart'): m17restart = config.get('m17', 'svcrestart') else: m17restart = str(999999999999) if config.has_option('m17', 'reboot'): m17reboot = config.get('m17', 'reboot') else: m17reboot = str(999999999999) if config.has_option('m17', 'shutdown'): m17shutdown = config.get('m17', 'shutdown') else: m17shutdown = str(999999999999) if config.has_option('m17', 'hostfiles'): m17hostfiles = config.get('m17', 'hostfiles') else: m17hostfiles = str(999999999999) # 8-Ball answers magic8ball = [ 'It is certain', 'It is decidedly so', 'Without a doubt', 'Yes definitely', 'You may rely on it', 'As I see it, yes', 'Most likely', 'Outlook good', 'Yes', 'Signs point to yes', 'Reply hazy try agn', 'Ask again later', 'Tell you later', 'Cannot predict now', 'Concentrate, ask agn', 'Dont count on it', 'My reply is no', 'My sources say no', 'Outlook not so good', 'Very doubtful' ] # Some Variables that are important later txtTransmitOldBin = '/usr/local/bin/texttransmit' txtTransmitNewBin = '/usr/local/bin/texttransmitd' if os.path.isfile(txtTransmitOldBin): txtTransmitBin = '/usr/local/bin/texttransmit' if os.path.isfile(txtTransmitNewBin): txtTransmitBin = '/usr/local/bin/texttransmitd' # Now run the loop while True: # Check that the process is running, if its not there is no point in trying to stop it. checkproc = subprocess.Popen( 'pgrep' + ' MMDVMHost', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if checkproc.stdout.readlines(): # This is the main loop that keeps waiting, we dont want to hammer the logs too often, every 30 secs should be enough. utcnow = datetime.datetime.utcnow() datenow = utcnow.strftime('%Y-%m-%d') dateminus60sec = datetime.datetime.utcnow() - datetime.timedelta(seconds=scan_rate) logstampnow = utcnow.strftime('%Y-%m-%d %H:%M:%S') logstampnowminus60sec = dateminus60sec.strftime('%Y-%m-%d %H:%M:%S') currentLog = mmdvmLogPath + '/' + mmdvmFileRoot + '-' + datenow + '.log' currentLogYSF = ysfGatewayLogPath + '/' + \ ysfGatewayFileRoot + '-' + datenow + '.log' loglist = [] # Open the MMDVMHost Log if os.path.isfile(currentLog): logfile = open(currentLog, 'r') loglist = logfile.readlines() logfile.close() # Parse the log lines for line in loglist: # We only care about logs in the last 60 secs if line[3:22] >= logstampnowminus60sec and line[3:22] <= logstampnow: dmrlocalfound= re.search('received RF voice header from ' + keeperCall + ' to ' + local_prefix + '([0-9])([0-9][0-9][0-9][0-9])',line) if dmrlocalfound: localverb=dmrlocalfound.group(1) localid=dmrlocalfound.group(2) os.system(f'{local_script} dmr "{localverb}" "{localid}"') # DMR Stop MMDVMHost # M: 2017-07-03 09:39:38.208 DMR Slot 2, received RF voice header from M1ABC to 123456 if str('received RF voice header from ' + keeperCall + ' to ' + dmrstop) in line: # Kill the Services os.system(r'systemctl stop mmdvmhost.timer') os.system(r'systemctl stop pistar-watchdog.timer') os.system(r'systemctl stop mmdvmhost.service') os.system(r'systemctl stop pistar-watchdog.service') # DMR Restart MMDVMHost # M: 2017-07-03 09:39:38.208 DMR Slot 2, received RF voice header from M1ABC to 123456 if str('received RF voice header from ' + keeperCall + ' to ' + dmrrestart) in line: # Restart the Services os.system(r'systemctl restart mmdvmhost.service') os.system(r'systemctl restart dmrgateway.service') time.sleep(30) # DMR Restart the OS # M: 2017-07-03 09:39:38.208 DMR Slot 2, received RF voice header from M1ABC to 123456 if str('received RF voice header from ' + keeperCall + ' to ' + dmrreboot) in line: # Restart the OS os.system(r'shutdown -r now') # DMR Shutdown the OS # M: 2017-07-03 09:39:38.208 DMR Slot 2, received RF voice header from M1ABC to 123456 if str('received RF voice header from ' + keeperCall + ' to ' + dmrshutdown) in line: # Shutdown the OS os.system(r'shutdown -h now') # DMR Update Hostfiles # M: 2017-07-03 09:39:38.208 DMR Slot 2, received RF voice header from M1ABC to 123456 if str('received RF voice header from ' + keeperCall + ' to ' + dmrhostfiles) in line: # Update Host files os.system(r'/usr/local/sbin/wpsd-hostfile-update') # DMR Reconnect WIFI # M: 2017-07-03 09:39:38.208 DMR Slot 2, received RF voice header from M1ABC to 123456 if str('received RF voice header from ' + keeperCall + ' to ' + dmrreconnect) in line: # trigger reconnect os.system( r'logger -t "[$$]" "Pi-Star --> Wifi Reconnect initiated <--"') os.system(r'wpa_cli reconfigure wlan0') os.system(r'ifdown wlan0 && sleep 3') os.system(r'ifup wlan0') os.system(r'wpa_cli scan') # P25 Stop MMDVMHost # M: 2017-08-08 08:02:43.352 P25, received RF transmission from M1ABC to TG 123456 if str('P25, received RF transmission from ' + keeperCall + ' to TG ' + p25stop) in line: # Kill the Services os.system(r'systemctl stop mmdvmhost.timer') os.system(r'systemctl stop pistar-watchdog.timer') os.system(r'systemctl stop mmdvmhost.service') os.system(r'systemctl stop pistar-watchdog.service') # P25 Restart MMDVMHost # M: 2017-08-08 08:02:43.352 P25, received RF transmission from M1ABC to TG 123456 if str('P25, received RF transmission from ' + keeperCall + ' to TG ' + p25restart) in line: # Restart the Services os.system(r'systemctl restart mmdvmhost.service') os.system(r'systemctl restart dmrgateway.service') time.sleep(30) # P25 Restart the OS # M: 2017-08-08 08:02:43.352 P25, received RF transmission from M1ABC to TG 123456 if str('P25, received RF transmission from ' + keeperCall + ' to TG ' + p25reboot) in line: # Restart the OS os.system(r'shutdown -r now') # P25 Shutdown the OS # M: 2017-08-08 08:02:43.352 P25, received RF transmission from M1ABC to TG 123456 if str('P25, received RF transmission from ' + keeperCall + ' to TG ' + p25shutdown) in line: # Shutdown the OS os.system(r'shutdown -h now') # P25 Update Hostfiles # M: 2017-08-08 08:02:43.352 P25, received RF transmission from M1ABC to TG 123456 if str('P25, received RF transmission from ' + keeperCall + ' to TG ' + p25hostfiles) in line: # Update Host Files os.system(r'/usr/local/sbin/wpsd-hostfile-update') # D-Star Stop MMDVMHost # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstarstop) in line: # Kill the Services os.system( txtTransmitBin + ' -text "Shutting down at keeper request" "' + dstarmodule + '"') time.sleep(5) os.system(r'systemctl stop mmdvmhost.timer') os.system(r'systemctl stop pistar-watchdog.timer') os.system(r'systemctl stop mmdvmhost.service') os.system(r'systemctl stop pistar-watchdog.service') # D-Star Restart MMDVMHost # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstarrestart) in line: # Restart the Services os.system( txtTransmitBin + ' -text "Restarting services at keeper request" "' + dstarmodule + '"') time.sleep(5) os.system(r'systemctl restart ircddbgateway.service') os.system(r'systemctl restart mmdvmhost.service') time.sleep(30) # D-Star Reboot the OS # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstarreboot) in line: # Kill the Services os.system( txtTransmitBin + ' -text "Rebooting OS at keeper request" "' + dstarmodule + '"') time.sleep(5) os.system(r'shutdown -r now') # D-Star Shutdown the OS # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstarshutdown) in line: # Shutdown os.system( txtTransmitBin + ' -text "Shutting down OS at keeper request" "' + dstarmodule + '"') time.sleep(5) os.system(r'shutdown -h now') # D-Star Hostfiles Update # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstarhostfiles) in line: # Update Host files os.system( txtTransmitBin + ' -text "Updating Hostfiles at keeper request" "' + dstarmodule + '"') time.sleep(5) os.system(r'/usr/local/sbin/wpsd-hostfile-update') # D-Star Get the current IP # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstargetip) in line: # Get the IP myIP = os.popen( '/bin/hostname -I | awk \'{print $1}\'').read() os.system(txtTransmitBin + ' -text "IP: ' + myIP + '" "' + dstarmodule + '"') # D-Star Get the wifi SSID # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstargetwifissid) in line: # Get the SSID if os.path.islink('/sys/class/net/wlan0'): ssid = os.popen( '/sbin/iwconfig wlan0 | grep ESSID | awk -F ":" \'{print $2}\' | sed \'s/"//g\'').read() os.system(txtTransmitBin + ' -text "SSID: ' + ssid + '" "' + dstarmodule + '"') else: os.system( txtTransmitBin + ' -text "WiFi: Not connected" "' + dstarmodule + '"') # D-Star Get the wifi RSSI # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstargetwifirssi) in line: # Get the SSID if os.path.islink('/sys/class/net/wlan0'): rssi = os.popen( '/sbin/iwconfig wlan0 | grep -i "signal level" | awk -F "=" \'{print $3}\'').read() os.system(txtTransmitBin + ' -text "RSSI: ' + rssi + '" "' + dstarmodule + '"') else: os.system( txtTransmitBin + ' -text "WiFi: Not connected" "' + dstarmodule + '"') # D-Star 8Ball # M: 2017-07-03 11:38:57.349 D-Star, received RF header from M1ABC /1234 to COMMAND1 if str('D-Star, received RF header from ' + keeperCall + ' ') and str(dstar8ball) in line: # Ask the 8Ball magic8ballanswer = random.choice(magic8ball) os.system(txtTransmitBin + ' -text "' + magic8ballanswer + '" "' + dstarmodule + '"') # YSF # M: 2017-07-13 19:50:43.464 YSF, received RF header from M1ABC to ALL if str('YSF, received RF header from ' + keeperCall + ' ') in line: # YSF Log Checking here logfileysf = open(currentLogYSF, 'r') loglistysf = logfileysf.readlines() logfileysf.close() checkproc = subprocess.Popen( 'pgrep' + ' YSFGateway', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if checkproc.stdout.readlines(): # Parse the log lines for lineysf in loglistysf: # We only care about logs in the last 60 secs if lineysf[3:22] >= logstampnowminus60sec and lineysf[3:22] <= logstampnow: # YSF Stop MMDVMHost # M: 2017-07-13 19:24:59.704 Trying to find non existent reflector with an id of 12345 if (str('Trying to find non existent') and str(ysfstop) in lineysf) or (str('Received Connect to') and str(ysfstop) in lineysf): # Kill the Services os.system( r'systemctl stop mmdvmhost.timer') os.system( r'systemctl stop pistar-watchdog.timer') os.system( r'systemctl stop mmdvmhost.service') os.system( r'systemctl stop pistar-watchdog.service') # YSF Restart MMDVMHost # M: 2017-07-13 19:24:59.704 Trying to find non existent reflector with an id of 12345 if (str('Trying to find non existent') and str(ysfrestart) in lineysf) or (str('Received Connect to') and str(ysfrestart) in lineysf): # Restart the Services os.system( r'systemctl restart ysfgateway.service') os.system( r'systemctl restart mmdvmhost.service') time.sleep(30) # YSF Reboot the OS # M: 2017-07-13 19:24:59.704 Trying to find non existent reflector with an id of 12345 if (str('Trying to find non existent') and str(ysfreboot) in lineysf) or (str('Received Connect to') and str(ysfreboot) in lineysf): # Reboot the OS os.system(r'shutdown -r now') # YSF Shutdown the OS # M: 2017-07-13 19:24:59.704 Trying to find non existent reflector with an id of 12345 if (str('Trying to find non existent') and str(ysfshutdown) in lineysf) or (str('Received Connect to') and str(ysfshutdown) in lineysf): # Shutdown the OS os.system(r'shutdown -h now') # YSF Update the Hostfiles # M: 2017-07-13 19:24:59.704 Trying to find non existent reflector with an id of 12345 if (str('Trying to find non existent') and str(ysfhostfiles) in lineysf) or (str('Received Connect to') and str(ysfhostfiles) in lineysf): # Update the host files os.system( r'/usr/local/sbin/wpsd-hostfile-update') # M17 Stop MMDVMHost # M: 2025-01-25 15:51:20.147 M17, received RF voice transmission from N1ADJ to SVCKILL if str('M17, received RF voice transmission from ' + keeperCall + ' to ' + m17stop) in line: # Kill the Services os.system(r'systemctl stop mmdvmhost.timer') os.system(r'systemctl stop pistar-watchdog.timer') os.system(r'systemctl stop mmdvmhost.service') os.system(r'systemctl stop pistar-watchdog.service') # M17 Restart MMDVMHost # M: 2025-01-25 15:51:20.147 M17, received RF voice transmission from N1ADJ to SVCKILL if str('M17, received RF voice transmission from ' + keeperCall + ' to ' + m17restart) in line: # Restart the Services os.system(r'systemctl restart mmdvmhost.service') os.system(r'systemctl restart m17gateway.service') time.sleep(30) # M17 Restart the OS # M: 2025-01-25 15:51:20.147 M17, received RF voice transmission from N1ADJ to SVCKILL if str('M17, received RF voice transmission from ' + keeperCall + ' to ' + m17reboot) in line: # Restart the OS os.system(r'shutdown -r now') # M17 Shutdown the OS # M: 2025-01-25 15:51:20.147 M17, received RF voice transmission from N1ADJ to SVCKILL if str('M17, received RF voice transmission from ' + keeperCall + ' to ' + m17shutdown) in line: # Shutdown the OS os.system(r'shutdown -h now') # M17 Update Hostfiles # M: 2025-01-25 15:51:20.147 M17, received RF voice transmission from N1ADJ to SVCKILL if str('M17, received RF voice transmission from ' + keeperCall + ' to ' + m17hostfiles) in line: # Update Host Files os.system(r'/usr/local/sbin/wpsd-hostfile-update') # This is the 30 second sleep before the next pass. time.sleep(scan_rate) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,59 @@ #!/bin/bash # example remote user hook de WD5GNR echo Loading user data . /home/pi-star/user-hook-data # Here is an example of the user-hook-data file # # #DMRID=XXXXXXXX #TG0001=3001 #TG0002=312681 #TG9999=93 # ignore everything but dmr if [ "$1" != "dmr" ] then exit 0 fi # we can pull your BMAPI key bmkey=$(grep apikey= /etc/bmapi.key | cut -d = -f 2) # read the verb (0-9) and the noun/argument (4 digits) VERB="$2" ARG="TG$3" N=$(echo $3 | cut -c4 ) TG="${!ARG}" echo $VERB " " $ARG if [ "$VERB" == "0" ] then python /usr/local/bin/bm_tg.py rmtg "$TG" 1 "$DMRID" "$bmkey" echo Removed $TG exit 0 fi if [ "$VERB" == "1" ] then python /usr/local/bin/bm_tg.py addtg "$TG" 1 "$DMRID" "$bmkey" echo Added $TG exit 0 fi if [ "$VERB" == 2 ] then RemoteCommand 7643 disable net$N exit 0 fi if [ "$VERB" == 3 ] then RemoteCommand 7643 enable net$N exit 0 fi exit 1 This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,55 @@ #!/usr/bin/env python3 # de WD5GNR # This script reads a verb (command), noun (tg #), your ESSID, and your BM API Key # It will add a static TG on timeslot 1 (verb=1 or verb=addtg) # It will remove a static TG on timeslot 1 (verb=0 or verb=rmtg) # exit code 0=ok, 1=failed, 2=bad verb, 3=wrong number of arguments import sys import requests def manage_talkgroup(verb, noun, slot, hotspot_id, bmkey): base_url = f'https://api.brandmeister.network/v2/device/{hotspot_id}/talkgroup' headers = {'Authorization': f'Bearer {bmkey}'} # add talkgrou if verb == '1' or verb == 'addtg': # Add static talkgroup to timeslot 1 payload = {'group': int(noun), 'slot': int(slot)} response = requests.post(base_url, json=payload, headers=headers) if response.status_code == 200: print(f'Successfully added talkgroup {noun} to timeslot {slot}.') return 0 else: print(f'Failed to add talkgroup {noun}. Status code: {response.status_code}') return 1 elif verb == '0' or verb == 'rmtg': # Remove static talkgroup delete_url = f'{base_url}/{slot}/{noun}' response = requests.delete(delete_url, headers=headers) if response.status_code == 200: print(f'Successfully removed talkgroup {noun}.') return 0 else: print(f'Failed to remove talkgroup {noun}. Status code: {response.status_code}') return 1 else: print('Invalid verb. Use 0 to add or 1 to remove a talkgroup.') return 2 if __name__ == '__main__': if len(sys.argv) != 6: print('Usage: bm_tg <verb> <noun> <slot> <node> <key>') print('verb: 0 to add a talkgroup, 1 to remove a talkgroup') print('noun: ID of the talkgroup') print('slot: The slot (if needed)') print('node: ID of the repeater') print('key: BM API Key') exit(3) else: verb = sys.argv[1] noun = sys.argv[2] slot = sys.argv[3] id = sys.argv[4] apikey = sys.argv[5] rc=manage_talkgroup(verb, noun, slot, id, apikey) exit(rc) This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,14 @@ # Sample user-hook-data file for remote-user-hook-example0 # We need your DMR ID DMRID=123456701 # hard to pull from /etc/dmrgateway # List of 4 digit TGs to map to real TGs TG0001=3001 TG0002=312681 TG9999=93 # order doesn't matter, but you do need 4 digits (e.g., don't do TG2=...) # If your user prefix is 77 then # 7710002 will activate 312681 as a static group # 7700002 will deactivate 312681 # 7730001 will activate DMR network #1 (as in WPSD admin dashboard) # 7720001 will deactivate DMR network #1