Compare commits

...

1 Commits

2 changed files with 174 additions and 1 deletions

View File

@ -10,6 +10,8 @@ from datetime import datetime
import kiss
import aprslib
import pick_pretty_description from aprs_to_callsign
MYCALL = os.environ.get("MYCALL", "N0CALL")
KISS_HOST = os.environ.get("KISS_HOST", "10.10.10.91")
KISS_PORT = os.environ.get("KISS_PORT", "8001")
@ -28,7 +30,7 @@ def parse_frame(date, frame):
except (aprslib.ParseError, aprslib.UnknownFormat) as exp:
logger.error(f"Failed to parse frame: {frame}")
return str(frame)
formatted_string = date.strftime('%H:%M:%S.%f')[:-3] + " " + "{} -> {} -> {}:".format(parsed["from"], parsed["via"], parsed["to"])
formatted_string = date.strftime('%H:%M:%S.%f')[:-3] + " " + "{} -> {} -> {}:".format(parsed["from"], parsed["via"], pick_pretty_description(parsed["to"])))
formatted_string += " <{:.4f} {:.4f}>".format(parsed["latitude"], parsed["longitude"]) if "longitude" in parsed and "latitude" in parsed else ""
formatted_string += " tUNIT: " + ",".join(parsed["tUNIT"]) if "tUNIT" in parsed else ""
formatted_string += " tPARM: " + ",".join(parsed["tPARM"]) if "tPARM" in parsed else ""

171
aprs_to_callsign.py Normal file
View File

@ -0,0 +1,171 @@
# source: http://aprs.org/aprs11/tocalls.txt
ALTNET_DESCRIPTION = 'An ALTNET is defined to be ANY AX.25 TOCALL that is NOT one of the normal APRS TOCALL'
TOCALLS = {
# slightly trasformed table from the source
'AP1WWX': 'TAPR T-238+ WX station',
'AP4Ry': 'APRS4R software interface',
'APnnnD': 'Painter Engineering uSmartDigi D-Gate DSTAR Gateway',
'APnnnU': 'Painter Engineering uSmartDigi Digipeater',
'APAF': 'AFilter.',
'APAG': 'AGATE',
'APAGW': "SV2AGW's AGWtracker",
'APA': 'AFilterX.',
'APAH': 'AHub',
'APAND1': 'APRSdroid (replaced by APDRxx',
'APAW': 'AGWPE',
'APB': 'Beacons or Rabbit TCPIP micros?',
'APBL': 'BigRedBee BeeLine',
'APBLO': 'MOdel Rocketry K7RKT',
'APC': 'Cellular applications',
'APCBB': 'for VE7UDP Blackberry Applications',
'APCLEY': 'EYTraker GPRS/GSM tracker by ZS6EY',
'APCLW': 'EYWeather GPRS/GSM WX station by ZS6EY',
'APCLEZ': 'Telit EZ10 GSM application ZS6CEY',
'APCY': 'Cybiko applications',
'APRSd': 'etc',
'APD4': 'UP4DAR platform',
'APDD': 'DV-RPTR Modem and Control Center Software',
'APDF': 'Automatic DF units',
'APDG': 'D-Star Gateways by G4KLX ircDDB',
'APDH': 'WinDV (DUTCH*Star DV Node for Windows)',
'APDInn': 'DIXPRS - Bela, HA5DI',
'APDK': 'KI4LKF g2_ircddb Dstar gateway software',
'APDO': 'ON8JL Standalone DStar Node',
'APDPRS': 'D-Star originated posits',
'APDR': 'APrsDRoid replaces old APAND1.',
'APDS': 'SP9UOB for dsDigi and ds-tracker',
'APDT': 'APRStouch Tone (DTMF)',
'APDU': 'U2APRS by JA7UDE',
'APDW': 'DireWolf, WB2OSZ',
'APE': 'Telemetry devices',
'APERQ': 'Experimental tracker by PE1RXQ',
'APF': 'Firenet',
'APFG': 'Flood Gage (KP4DJT)',
'APG': 'Gates, etc',
'APGO': 'for AA3NJ PDA application',
'APH': 'HamHud, etc',
'APHK': 'for LA1BR tracker/digipeater',
'API': 'Icom, etc',
'APICQ': 'for ICQ',
'APJA': 'JavAPRS',
'APJE': 'JeAPRS',
'APJI': 'jAPRSIgate',
'APJS': 'javAPRSSrvr',
'APK0': "Kenwood TH-D7's",
'APK003': 'Kenwood TH-D72',
'APK1': "Kenwood D700's",
'APR102': 'Kenwood D710',
'APKRAM': 'KRAMstuff.com - Mark. G7LEU',
'APL': 'Linux applications',
'APM': 'MacAPRS, etc',
'APN': 'Network nodes, digis, etc',
'APN3': 'Kantronics KPC-3 rom versions',
'APN9': 'Kantronics KPC-9612 Roms',
'APNA': "WB6ZSU's APRServe",
'APND': 'DIGI_NED ssid routing ok',
'APNM': 'MJF TNC roms',
'APNP': 'Paccom TNC roms',
'APNT': "SV2AGW's TNT tnc as a digi",
'APNU': 'UIdigi; ssid routing ok',
'APN': 'TNC-X (K6DBG)',
'APNK01': 'Kenwood D700 (APK101) type',
'APNK80': 'KAM version 8.0',
'APNKMP': 'KAM+',
'APOA': 'OpenAPRS - Greg Carter',
'APOT': 'OpenTrack',
'APOD1w': 'OpenTrack with 1 wire WX',
'APOU2k': 'OpenTrack for Ultimeter',
'APP': 'pocketAPRS, etc',
'APPT': 'KetaiTracker by JF6LZE, Takeki (msg capable)',
'APQ': 'Earthquake data',
'APR8': 'APRSdos versions 800+',
'APRD': 'APRSdata, APRSdr',
'APRG': 'aprsg igate software, OH2GVE',
'APRHH2': 'HamHud 2',
'APRK': 'APRStk',
'APRNOW': 'W5GGW ipad application',
'APRRT': 'RPC electronics',
'APRS': 'Generic, (obsolete. Digis should use APNxxx instead)',
'APR': '>APRSmax 40 ',
'APR': "OH2MQK's RX-igate <39",
'APRTLM': "used in MIM's and Mic-lites, etc",
'APRtfc': 'APRStraffic',
'APRST': 'APRStt (Touch tone)',
'APSK63': 'APRS Messenger -over-PSK63',
'APSK25': 'APRS Messenger GMSK-250',
'APTIGR': 'TigerTrack',
'APTT': 'Tiny Track',
'APT2': 'Tiny Track II',
'APT3': 'Tiny Track III',
'APTA': "K4ATM's tiny track",
'APTW': 'Byons WXTrac',
'APTV': 'for ATV/APRN and SSTV application',
'APU1': 'UIview 16 bit applications',
'APU2': 'UIview 32 bit apps',
'APU3': 'UIview terminal program',
'APV': 'VoIP Voice over Internet application',
'APVR': 'IRLP',
'APVL': 'I-LINK',
'APVE': 'ECHO link',
'APW': 'WinAPRS, etc',
'APWS': "DF4IAN's WS2300 WX station",
'APWM': 'APRSISCE KJ4ERJ',
'APWW': 'APRSISCE win32 version',
'AP': 'Xastir',
'APR': 'Xrouter',
'APY': 'Yeasu',
'APZ': 'Experimental',
'APZ0': 'Xastir (old versions. See APX) ssid routing ok',
'APZMDR': 'HaMDR trackers - hessu * hes.iki.fi' ,
'APZPAD': 'Smart Palm',
'APZWIT': 'MAP27 radio (Mountain Rescue) EI7IG',
}
# def filter_by_dest(aprs_destination):
# '''
# Just a shorthand to filter through the dict
# '''
# return { key:TOCALLS[key] for key in TOCALLS.keys() if aprs_destination.lower() in key.lower()}
def search_for_dest(aprs_destination):
i = 2
filter_by_dest = lambda to_call: { key:TOCALLS[key] for key in TOCALLS.keys() if to_call.lower() in key.lower()}
pick_by_prefix = lambda i: filter_by_dest(aprs_destination[:i])
results_ammount = lambda i: len(pick_by_prefix(i))
results = {aprs_destination: ''}
while results_ammount(i) > 0:
if i == 6:
break
i += 1
if results_ammount(i) == 1:
return pick_by_prefix(i)
else:
return results
# list(pick_description(parsed["to"]).values())[0]
def pick_description(aprs_destination, filter_altnets=True):
descr = ALTNET_DESCRIPTION if not filter_altnets else ''
match_tocall = lambda x: aprs_destination.lower().startswith(x.lower())
if not match_tocall('ap'):
# ALL, BEACON, CQ, QST, GPSxxx
if match_tocall('ALL'):
descr = 'ALL'
elif match_tocall('BEACON'):
descr = 'BEACON'
elif match_tocall('CQ'):
descr = 'CQ'
elif match_tocall('QST'):
descr = 'QST'
elif match_tocall('GPS'):
descr = 'GPS'
return {aprs_destination: descr}
else:
return search_for_dest(aprs_destination)
def pick_pretty_description(aprs_destination, filter_altnets=True):
'''
For now it's just two first words from description.
'''
result = pick_description(aprs_destination, filter_altnets)
return ' '.join(list(result.values())[0].split()[:2])