APRS IMPLEMENTATION

This commit is contained in:
Daniele Marra 2020-09-18 21:03:51 +02:00 committed by GitHub
parent 08f6669bd3
commit f70fc26707
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 408 additions and 246 deletions

View File

@ -104,6 +104,7 @@ def build_config(_config_file):
CONFIG = {} CONFIG = {}
CONFIG['GLOBAL'] = {} CONFIG['GLOBAL'] = {}
CONFIG['APRS'] = {}
CONFIG['REPORTS'] = {} CONFIG['REPORTS'] = {}
CONFIG['LOGGER'] = {} CONFIG['LOGGER'] = {}
CONFIG['ALIASES'] = {} CONFIG['ALIASES'] = {}
@ -122,6 +123,15 @@ def build_config(_config_file):
'TG1_ACL': config.get(section, 'TGID_TS1_ACL'), 'TG1_ACL': config.get(section, 'TGID_TS1_ACL'),
'TG2_ACL': config.get(section, 'TGID_TS2_ACL') 'TG2_ACL': config.get(section, 'TGID_TS2_ACL')
}) })
elif section == 'APRS':
CONFIG['APRS'].update({
'ENABLED': config.getboolean(section, 'ENABLED'),
'CALLSIGN': config.get(section, 'CALLSIGN'),
'REPORT_INTERVAL': config.getint(section, 'REPORT_INTERVAL'),
'SERVER': config.get(section, 'SERVER'),
'MESSAGE': config.get(section, 'MESSAGE')
})
elif section == 'REPORTS': elif section == 'REPORTS':
CONFIG['REPORTS'].update({ CONFIG['REPORTS'].update({

View File

@ -1,241 +1,254 @@
# PROGRAM-WIDE PARAMETERS GO HERE # PROGRAM-WIDE PARAMETERS GO HERE
# PATH - working path for files, leave it alone unless you NEED to change it # PATH - working path for files, leave it alone unless you NEED to change it
# PING_TIME - the interval that peers will ping the master, and re-try registraion # PING_TIME - the interval that peers will ping the master, and re-try registraion
# - how often the Master maintenance loop runs # - how often the Master maintenance loop runs
# MAX_MISSED - how many pings are missed before we give up and re-register # MAX_MISSED - how many pings are missed before we give up and re-register
# - number of times the master maintenance loop runs before de-registering a peer # - number of times the master maintenance loop runs before de-registering a peer
# #
# ACLs: # ACLs:
# #
# Access Control Lists are a very powerful tool for administering your system. # Access Control Lists are a very powerful tool for administering your system.
# But they consume packet processing time. Disable them if you are not using them. # But they consume packet processing time. Disable them if you are not using them.
# But be aware that, as of now, the configuration stanzas still need the ACL # But be aware that, as of now, the configuration stanzas still need the ACL
# sections configured even if you're not using them. # sections configured even if you're not using them.
# #
# REGISTRATION ACLS ARE ALWAYS USED, ONLY SUBSCRIBER AND TGID MAY BE DISABLED!!! # REGISTRATION ACLS ARE ALWAYS USED, ONLY SUBSCRIBER AND TGID MAY BE DISABLED!!!
# #
# The 'action' May be PERMIT|DENY # The 'action' May be PERMIT|DENY
# Each entry may be a single radio id, or a hypenated range (e.g. 1-2999) # Each entry may be a single radio id, or a hypenated range (e.g. 1-2999)
# Format: # Format:
# ACL = 'action:id|start-end|,id|start-end,....' # ACL = 'action:id|start-end|,id|start-end,....'
# --for example-- # --for example--
# SUB_ACL: DENY:1,1000-2000,4500-60000,17 # SUB_ACL: DENY:1,1000-2000,4500-60000,17
# #
# ACL Types: # ACL Types:
# REG_ACL: peer radio IDs for registration (only used on HBP master systems) # REG_ACL: peer radio IDs for registration (only used on HBP master systems)
# SUB_ACL: subscriber IDs for end-users # SUB_ACL: subscriber IDs for end-users
# TGID_TS1_ACL: destination talkgroup IDs on Timeslot 1 # TGID_TS1_ACL: destination talkgroup IDs on Timeslot 1
# TGID_TS2_ACL: destination talkgroup IDs on Timeslot 2 # TGID_TS2_ACL: destination talkgroup IDs on Timeslot 2
# #
# ACLs may be repeated for individual systems if needed for granularity # ACLs may be repeated for individual systems if needed for granularity
# Global ACLs will be processed BEFORE the system level ACLs # Global ACLs will be processed BEFORE the system level ACLs
# Packets will be matched against all ACLs, GLOBAL first. If a packet 'passes' # Packets will be matched against all ACLs, GLOBAL first. If a packet 'passes'
# All elements, processing continues. Packets are discarded at the first # All elements, processing continues. Packets are discarded at the first
# negative match, or 'reject' from an ACL element. # negative match, or 'reject' from an ACL element.
# #
# If you do not wish to use ACLs, set them to 'PERMIT:ALL' # If you do not wish to use ACLs, set them to 'PERMIT:ALL'
# TGID_TS1_ACL in the global stanza is used for OPENBRIDGE systems, since all # TGID_TS1_ACL in the global stanza is used for OPENBRIDGE systems, since all
# traffic is passed as TS 1 between OpenBridges # traffic is passed as TS 1 between OpenBridges
[GLOBAL] [GLOBAL]
PATH: ./ PATH: ./
PING_TIME: 5 PING_TIME: 5
MAX_MISSED: 3 MAX_MISSED: 3
USE_ACL: True USE_ACL: True
REG_ACL: PERMIT:ALL REG_ACL: PERMIT:ALL
SUB_ACL: DENY:1 SUB_ACL: DENY:1
TGID_TS1_ACL: PERMIT:ALL TGID_TS1_ACL: PERMIT:ALL
TGID_TS2_ACL: PERMIT:ALL TGID_TS2_ACL: PERMIT:ALL
# APRS - BY IU7IGU
# NOT YET WORKING: NETWORK REPORTING CONFIGURATION # Enabling "APRS" will configure APRS-Beaconing of Master's connection
# Enabling "REPORT" will configure a socket-based reporting # like repeater and hotspots.
# system that will send the configuration and other items # REPORT_INTERVAL in Minute (ALLOW only > 3 Minutes)
# to a another process (local or remote) that may process # CALLSIGN: Callsign that will pubblish data on aprs server
# the information for some useful purpose, like a web dashboard. # MESSAGE: This message will print on APRS description together RX and TX Frequency
#
# REPORT - True to enable, False to disable [APRS]
# REPORT_INTERVAL - Seconds between reports ENABLED: True
# REPORT_PORT - TCP port to listen on if "REPORT_NETWORKS" = NETWORK REPORT_INTERVAL: 5
# REPORT_CLIENTS - comma separated list of IPs you will allow clients CALLSIGN:HB1LNK-11
# to connect on. Entering a * will allow all. SERVER:euro.aprs2.net
# MESSAGE:Connesso ad HBLINK
# ****FOR NOW MUST BE TRUE - USE THE LOOPBACK IF YOU DON'T USE THIS!!!****
[REPORTS] # NOT YET WORKING: NETWORK REPORTING CONFIGURATION
REPORT: True # Enabling "REPORT" will configure a socket-based reporting
REPORT_INTERVAL: 60 # system that will send the configuration and other items
REPORT_PORT: 4321 # to a another process (local or remote) that may process
REPORT_CLIENTS: 127.0.0.1 # the information for some useful purpose, like a web dashboard.
#
# REPORT - True to enable, False to disable
# SYSTEM LOGGER CONFIGURAITON # REPORT_INTERVAL - Seconds between reports
# This allows the logger to be configured without chaning the individual # REPORT_PORT - TCP port to listen on if "REPORT_NETWORKS" = NETWORK
# python logger stuff. LOG_FILE should be a complete path/filename for *your* # REPORT_CLIENTS - comma separated list of IPs you will allow clients
# system -- use /dev/null for non-file handlers. # to connect on. Entering a * will allow all.
# LOG_HANDLERS may be any of the following, please, no spaces in the #
# list if you use several: # ****FOR NOW MUST BE TRUE - USE THE LOOPBACK IF YOU DON'T USE THIS!!!****
# null [REPORTS]
# console REPORT: True
# console-timed REPORT_INTERVAL: 60
# file REPORT_PORT: 4321
# file-timed REPORT_CLIENTS: 127.0.0.1
# syslog
# LOG_LEVEL may be any of the standard syslog logging levels, though
# as of now, DEBUG, INFO, WARNING and CRITICAL are the only ones # SYSTEM LOGGER CONFIGURAITON
# used. # This allows the logger to be configured without chaning the individual
# # python logger stuff. LOG_FILE should be a complete path/filename for *your*
[LOGGER] # system -- use /dev/null for non-file handlers.
LOG_FILE: /tmp/hblink.log # LOG_HANDLERS may be any of the following, please, no spaces in the
LOG_HANDLERS: console-timed # list if you use several:
LOG_LEVEL: DEBUG # null
LOG_NAME: HBlink # console
# console-timed
# DOWNLOAD AND IMPORT SUBSCRIBER, PEER and TGID ALIASES # file
# Ok, not the TGID, there's no master list I know of to download # file-timed
# This is intended as a facility for other applcations built on top of # syslog
# HBlink to use, and will NOT be used in HBlink directly. # LOG_LEVEL may be any of the standard syslog logging levels, though
# STALE_DAYS is the number of days since the last download before we # as of now, DEBUG, INFO, WARNING and CRITICAL are the only ones
# download again. Don't be an ass and change this to less than a few days. # used.
[ALIASES] #
TRY_DOWNLOAD: True [LOGGER]
PATH: ./ LOG_FILE: /tmp/hblink.log
PEER_FILE: peer_ids.json LOG_HANDLERS: console-timed
SUBSCRIBER_FILE: subscriber_ids.json LOG_LEVEL: DEBUG
TGID_FILE: talkgroup_ids.json LOG_NAME: HBlink
PEER_URL: https://www.radioid.net/static/rptrs.json
SUBSCRIBER_URL: https://www.radioid.net/static/users.json # DOWNLOAD AND IMPORT SUBSCRIBER, PEER and TGID ALIASES
STALE_DAYS: 7 # Ok, not the TGID, there's no master list I know of to download
# This is intended as a facility for other applcations built on top of
# OPENBRIDGE INSTANCES - DUPLICATE SECTION FOR MULTIPLE CONNECTIONS # HBlink to use, and will NOT be used in HBlink directly.
# OpenBridge is a protocol originall created by DMR+ for connection between an # STALE_DAYS is the number of days since the last download before we
# IPSC2 server and Brandmeister. It has been implemented here at the suggestion # download again. Don't be an ass and change this to less than a few days.
# of the Brandmeister team as a way to legitimately connect HBlink to the [ALIASES]
# Brandemiester network. TRY_DOWNLOAD: True
# It is recommended to name the system the ID of the Brandmeister server that PATH: ./
# it connects to, but is not necessary. TARGET_IP and TARGET_PORT are of the PEER_FILE: peer_ids.json
# Brandmeister or IPSC2 server you are connecting to. PASSPHRASE is the password SUBSCRIBER_FILE: subscriber_ids.json
# that must be agreed upon between you and the operator of the server you are TGID_FILE: talkgroup_ids.json
# connecting to. NETWORK_ID is a number in the format of a DMR Radio ID that PEER_URL: https://www.radioid.net/static/rptrs.json
# will be sent to the other server to identify this connection. SUBSCRIBER_URL: https://www.radioid.net/static/users.json
# other parameters follow the other system types. STALE_DAYS: 7
#
# ACLs: # OPENBRIDGE INSTANCES - DUPLICATE SECTION FOR MULTIPLE CONNECTIONS
# OpenBridge does not 'register', so registration ACL is meaningless. # OpenBridge is a protocol originall created by DMR+ for connection between an
# OpenBridge passes all traffic on TS1, so there is only 1 TGID ACL. # IPSC2 server and Brandmeister. It has been implemented here at the suggestion
# Otherwise ACLs work as described in the global stanza # of the Brandmeister team as a way to legitimately connect HBlink to the
[OBP-1] # Brandemiester network.
MODE: OPENBRIDGE # It is recommended to name the system the ID of the Brandmeister server that
ENABLED: True # it connects to, but is not necessary. TARGET_IP and TARGET_PORT are of the
IP: # Brandmeister or IPSC2 server you are connecting to. PASSPHRASE is the password
PORT: 62035 # that must be agreed upon between you and the operator of the server you are
NETWORK_ID: 3129100 # connecting to. NETWORK_ID is a number in the format of a DMR Radio ID that
PASSPHRASE: password # will be sent to the other server to identify this connection.
TARGET_IP: 1.2.3.4 # other parameters follow the other system types.
TARGET_PORT: 62035 #
USE_ACL: True # ACLs:
SUB_ACL: DENY:1 # OpenBridge does not 'register', so registration ACL is meaningless.
TGID_ACL: PERMIT:ALL # OpenBridge passes all traffic on TS1, so there is only 1 TGID ACL.
# Otherwise ACLs work as described in the global stanza
# MASTER INSTANCES - DUPLICATE SECTION FOR MULTIPLE MASTERS [OBP-1]
# HomeBrew Protocol Master instances go here. MODE: OPENBRIDGE
# IP may be left blank if there's one interface on your system. ENABLED: True
# Port should be the port you want this master to listen on. It must be unique IP:
# and unused by anything else. PORT: 62035
# Repeat - if True, the master repeats traffic to peers, False, it does nothing. NETWORK_ID: 3129100
# PASSPHRASE: password
# MAX_PEERS -- maximun number of peers that may be connect to this master TARGET_IP: 1.2.3.4
# at any given time. This is very handy if you're allowing hotspots to TARGET_PORT: 62035
# connect, or using a limited computer like a Raspberry Pi. USE_ACL: True
# SUB_ACL: DENY:1
# ACLs: TGID_ACL: PERMIT:ALL
# See comments in the GLOBAL stanza
[MASTER-1] # MASTER INSTANCES - DUPLICATE SECTION FOR MULTIPLE MASTERS
MODE: MASTER # HomeBrew Protocol Master instances go here.
ENABLED: True # IP may be left blank if there's one interface on your system.
REPEAT: True # Port should be the port you want this master to listen on. It must be unique
MAX_PEERS: 10 # and unused by anything else.
EXPORT_AMBE: False # Repeat - if True, the master repeats traffic to peers, False, it does nothing.
IP: #
PORT: 54000 # MAX_PEERS -- maximun number of peers that may be connect to this master
PASSPHRASE: s3cr37w0rd # at any given time. This is very handy if you're allowing hotspots to
GROUP_HANGTIME: 5 # connect, or using a limited computer like a Raspberry Pi.
USE_ACL: True #
REG_ACL: DENY:1 # ACLs:
SUB_ACL: DENY:1 # See comments in the GLOBAL stanza
TGID_TS1_ACL: PERMIT:ALL [MASTER-1]
TGID_TS2_ACL: PERMIT:ALL MODE: MASTER
ENABLED: True
# PEER INSTANCES - DUPLICATE SECTION FOR MULTIPLE PEERS REPEAT: True
# There are a LOT of errors in the HB Protocol specifications on this one! MAX_PEERS: 10
# MOST of these items are just strings and will be properly dealt with by the program EXPORT_AMBE: False
# The TX & RX Frequencies are 9-digit numbers, and are the frequency in Hz. IP:
# Latitude is an 8-digit unsigned floating point number. PORT: 54000
# Longitude is a 9-digit signed floating point number. PASSPHRASE: s3cr37w0rd
# Height is in meters GROUP_HANGTIME: 5
# Setting Loose to True relaxes the validation on packets received from the master. USE_ACL: True
# This will allow HBlink to connect to a non-compliant system such as XLXD, DMR+ etc. REG_ACL: DENY:1
# SUB_ACL: DENY:1
# ACLs: TGID_TS1_ACL: PERMIT:ALL
# See comments in the GLOBAL stanza TGID_TS2_ACL: PERMIT:ALL
[REPEATER-1]
MODE: PEER # PEER INSTANCES - DUPLICATE SECTION FOR MULTIPLE PEERS
ENABLED: True # There are a LOT of errors in the HB Protocol specifications on this one!
LOOSE: False # MOST of these items are just strings and will be properly dealt with by the program
EXPORT_AMBE: False # The TX & RX Frequencies are 9-digit numbers, and are the frequency in Hz.
IP: # Latitude is an 8-digit unsigned floating point number.
PORT: 54001 # Longitude is a 9-digit signed floating point number.
MASTER_IP: 172.16.1.1 # Height is in meters
MASTER_PORT: 54000 # Setting Loose to True relaxes the validation on packets received from the master.
PASSPHRASE: homebrew # This will allow HBlink to connect to a non-compliant system such as XLXD, DMR+ etc.
CALLSIGN: W1ABC #
RADIO_ID: 312000 # ACLs:
RX_FREQ: 449000000 # See comments in the GLOBAL stanza
TX_FREQ: 444000000 [REPEATER-1]
TX_POWER: 25 MODE: PEER
COLORCODE: 1 ENABLED: True
SLOTS: 1 LOOSE: False
LATITUDE: 38.0000 EXPORT_AMBE: False
LONGITUDE: -095.0000 IP:
HEIGHT: 75 PORT: 54001
LOCATION: Anywhere, USA MASTER_IP: 172.16.1.1
DESCRIPTION: This is a cool repeater MASTER_PORT: 54000
URL: www.w1abc.org PASSPHRASE: homebrew
SOFTWARE_ID: 20170620 CALLSIGN: W1ABC
PACKAGE_ID: MMDVM_HBlink RADIO_ID: 312000
GROUP_HANGTIME: 5 RX_FREQ: 449000000
OPTIONS: TX_FREQ: 444000000
USE_ACL: True TX_POWER: 25
SUB_ACL: DENY:1 COLORCODE: 1
TGID_TS1_ACL: PERMIT:ALL SLOTS: 1
TGID_TS2_ACL: PERMIT:ALL LATITUDE: 38.0000
LONGITUDE: -095.0000
[XLX-1] HEIGHT: 75
MODE: XLXPEER LOCATION: Anywhere, USA
ENABLED: True DESCRIPTION: This is a cool repeater
LOOSE: True URL: www.w1abc.org
EXPORT_AMBE: False SOFTWARE_ID: 20170620
IP: PACKAGE_ID: MMDVM_HBlink
PORT: 54002 GROUP_HANGTIME: 5
MASTER_IP: 172.16.1.1 OPTIONS:
MASTER_PORT: 62030 USE_ACL: True
PASSPHRASE: passw0rd SUB_ACL: DENY:1
CALLSIGN: W1ABC TGID_TS1_ACL: PERMIT:ALL
RADIO_ID: 312000 TGID_TS2_ACL: PERMIT:ALL
RX_FREQ: 449000000
TX_FREQ: 444000000 [XLX-1]
TX_POWER: 25 MODE: XLXPEER
COLORCODE: 1 ENABLED: True
SLOTS: 1 LOOSE: True
LATITUDE: 38.0000 EXPORT_AMBE: False
LONGITUDE: -095.0000 IP:
HEIGHT: 75 PORT: 54002
LOCATION: Anywhere, USA MASTER_IP: 172.16.1.1
DESCRIPTION: This is a cool repeater MASTER_PORT: 62030
URL: www.w1abc.org PASSPHRASE: passw0rd
SOFTWARE_ID: 20170620 CALLSIGN: W1ABC
PACKAGE_ID: MMDVM_HBlink RADIO_ID: 312000
GROUP_HANGTIME: 5 RX_FREQ: 449000000
XLXMODULE: 4004 TX_FREQ: 444000000
USE_ACL: True TX_POWER: 25
SUB_ACL: DENY:1 COLORCODE: 1
TGID_TS1_ACL: PERMIT:ALL SLOTS: 1
TGID_TS2_ACL: PERMIT:ALL LATITUDE: 38.0000
LONGITUDE: -095.0000
HEIGHT: 75
LOCATION: Anywhere, USA
DESCRIPTION: This is a cool repeater
URL: www.w1abc.org
SOFTWARE_ID: 20170620
PACKAGE_ID: MMDVM_HBlink
GROUP_HANGTIME: 5
XLXMODULE: 4004
USE_ACL: True
SUB_ACL: DENY:1
TGID_TS1_ACL: PERMIT:ALL
TGID_TS2_ACL: PERMIT:ALL

149
hblink.py
View File

@ -35,6 +35,9 @@ from hashlib import sha256, sha1
from hmac import new as hmac_new, compare_digest from hmac import new as hmac_new, compare_digest
from time import time from time import time
from collections import deque from collections import deque
import aprslib
import os
# Twisted is pretty important, so I keep it separate # Twisted is pretty important, so I keep it separate
from twisted.internet.protocol import DatagramProtocol, Factory, Protocol from twisted.internet.protocol import DatagramProtocol, Factory, Protocol
@ -66,6 +69,8 @@ __email__ = 'n0mjs@me.com'
# Global variables used whether we are a module or __main__ # Global variables used whether we are a module or __main__
systems = {} systems = {}
open("nom_aprs","w").close
# Timed loop used for reporting HBP status # Timed loop used for reporting HBP status
def config_reports(_config, _factory): def config_reports(_config, _factory):
def reporting_loop(_logger, _server): def reporting_loop(_logger, _server):
@ -80,10 +85,10 @@ def config_reports(_config, _factory):
reporting = task.LoopingCall(reporting_loop, logger, report_server) reporting = task.LoopingCall(reporting_loop, logger, report_server)
reporting.start(_config['REPORTS']['REPORT_INTERVAL']) reporting.start(_config['REPORTS']['REPORT_INTERVAL'])
return report_server return report_server
# Shut ourselves down gracefully by disconnecting from the masters and peers. # Shut ourselves down gracefully by disconnecting from the masters and peers.
def hblink_handler(_signal, _frame): def hblink_handler(_signal, _frame):
for system in systems: for system in systems:
@ -104,6 +109,7 @@ def acl_check(_id, _acl):
# OPENBRIDGE CLASS # OPENBRIDGE CLASS
#************************************************ #************************************************
class OPENBRIDGE(DatagramProtocol): class OPENBRIDGE(DatagramProtocol):
def __init__(self, _name, _config, _report): def __init__(self, _name, _config, _report):
# Define a few shortcuts to make the rest of the class more readable # Define a few shortcuts to make the rest of the class more readable
@ -112,7 +118,9 @@ class OPENBRIDGE(DatagramProtocol):
self._report = _report self._report = _report
self._config = self._CONFIG['SYSTEMS'][self._system] self._config = self._CONFIG['SYSTEMS'][self._system]
self._laststrid = deque([], 20) self._laststrid = deque([], 20)
def dereg(self): def dereg(self):
logger.info('(%s) is mode OPENBRIDGE. No De-Registration required, continuing shutdown', self._system) logger.info('(%s) is mode OPENBRIDGE. No De-Registration required, continuing shutdown', self._system)
@ -474,8 +482,18 @@ class HBSYSTEM(DatagramProtocol):
and self._peers[_peer_id]['SOCKADDR'] == _sockaddr: and self._peers[_peer_id]['SOCKADDR'] == _sockaddr:
logger.info('(%s) Peer is closing down: %s (%s)', self._system, self._peers[_peer_id]['CALLSIGN'], int_id(_peer_id)) logger.info('(%s) Peer is closing down: %s (%s)', self._system, self._peers[_peer_id]['CALLSIGN'], int_id(_peer_id))
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr) self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
if self._CONFIG['APRS']['ENABLED']:
fn = 'nom_aprs'
f = open(fn)
output = []
for line in f:
if not str(int_id(_peer_id)) in line:
output.append(line)
f.close()
f = open(fn, 'w')
f.writelines(output)
f.close()
del self._peers[_peer_id] del self._peers[_peer_id]
else: else:
_peer_id = _data[4:8] # Configure Command _peer_id = _data[4:8] # Configure Command
if _peer_id in self._peers \ if _peer_id in self._peers \
@ -502,6 +520,124 @@ class HBSYSTEM(DatagramProtocol):
self.send_peer(_peer_id, b''.join([RPTACK, _peer_id])) self.send_peer(_peer_id, b''.join([RPTACK, _peer_id]))
logger.info('(%s) Peer %s (%s) has sent repeater configuration', self._system, _this_peer['CALLSIGN'], _this_peer['RADIO_ID']) logger.info('(%s) Peer %s (%s) has sent repeater configuration', self._system, _this_peer['CALLSIGN'], _this_peer['RADIO_ID'])
#APRS IMPLEMENTATION
conta = 0
lista_blocco=['ysf', 'xlx', 'nxdn', 'dstar', 'echolink','p25', 'svx']
if self._CONFIG['APRS']['ENABLED'] and not str(_this_peer['CALLSIGN'].decode('UTF-8')).replace(' ', '').isalpha() :
file = open("nom_aprs","r")
linee = file.readlines()
file.close()
for link in lista_blocco:
if int(str(_this_peer['CALLSIGN'].decode('UTF-8')).replace(' ', '').find(link.upper())) == 0:
conta = conta + 1
if len(linee) > 0:
logging.info('Leggo')
for linea in linee:
dati_l = linea.split(':')
if str(_this_peer['RADIO_ID']) == str(dati_l[1]):
conta = conta + 1
if conta == 0:
file=open("nom_aprs",'a')
if len(str(_this_peer['RADIO_ID'])) > 7:
id_pr=int(str(_this_peer['RADIO_ID'])[-2:])
callsign_u=str(_this_peer['CALLSIGN'].decode('UTF-8'))+"-"+str(id_pr)
file.write(callsign_u.replace(' ', '')+ ":"+ str(_this_peer['RADIO_ID']) +":"+ str(_this_peer['RX_FREQ'].decode('UTF-8')) + ":" + str(_this_peer['TX_FREQ'].decode('UTF-8'))+ ":" + str(_this_peer['LATITUDE'].decode('UTF-8')) + ":" + str(_this_peer['LONGITUDE'].decode('UTF-8')) + "\n")
file.close()
else:
file.write(str(_this_peer['CALLSIGN'].decode('UTF-8')).replace(' ', '')+ ":"+ str(_this_peer['RADIO_ID']) +":"+ str(_this_peer['RX_FREQ'].decode('UTF-8')) + ":" + str(_this_peer['TX_FREQ'].decode('UTF-8'))+ ":" + str(_this_peer['LATITUDE'].decode('UTF-8')) + ":" + str(_this_peer['LONGITUDE'].decode('UTF-8')) + "\n")
file.close()
else:
if conta == 0:
file=open("nom_aprs",'a')
if len(str(_this_peer['RADIO_ID'])) > 7:
id_pr=int(str(_this_peer['RADIO_ID'])[-2:])
callsign_u=str(_this_peer['CALLSIGN'].decode('UTF-8'))+"-"+str(id_pr)
file.write(callsign_u.replace(' ', '')+ ":"+ str(_this_peer['RADIO_ID']) +":"+ str(_this_peer['RX_FREQ'].decode('UTF-8')) + ":" + str(_this_peer['TX_FREQ'].decode('UTF-8'))+ ":" + str(_this_peer['LATITUDE'].decode('UTF-8')) + ":" + str(_this_peer['LONGITUDE'].decode('UTF-8')) + "\n")
file.close()
else:
file.write(str(_this_peer['CALLSIGN'].decode('UTF-8')).replace(' ', '')+ ":"+ str(_this_peer['RADIO_ID']) +":"+ str(_this_peer['RX_FREQ'].decode('UTF-8')) + ":" + str(_this_peer['TX_FREQ'].decode('UTF-8'))+ ":" + str(_this_peer['LATITUDE'].decode('UTF-8')) + ":" + str(_this_peer['LONGITUDE'].decode('UTF-8')) + "\n")
file.close()
def sendAprs():
AIS = aprslib.IS(str(self._CONFIG['APRS']['CALLSIGN']), passwd=aprslib.passcode(str(self._CONFIG['APRS']['CALLSIGN'])), host=str(self._CONFIG['APRS']['SERVER']), port=14580)
AIS.connect()
f = open('nom_aprs', 'r')
lines = f.readlines()
if lines:
for line in lines:
if line != ' ':
lat_verso = ''
lon_verso = ''
dati = line.split(":")
d1_c = int(float(dati[4]))
d2_c = int(float(dati[5]))
if d1_c < 0:
d1 = abs(d1_c)
dm1=abs(float(dati[4])) - d1
dm1_s= float(dm1) * 60
dm1_u="{:.4f}".format(dm1_s)
if d1 < 10 and d1 > -10:
lat_utile='0'+str(d1)+str(dm1_u)
else:
lat_utile = str(d1)+str(dm1_u)
lat_verso = 'S'
else:
d1 = int(float(dati[4]))
dm1=float(dati[4]) - d1
dm1_s= float(dm1) * 60
dm1_u="{:.4f}".format(dm1_s)
if d1 < 10 and d1 > -10:
lat_utile='0'+str(d1)+str(dm1_u)
else:
lat_utile = str(d1)+str(dm1_u)
lat_verso = 'N'
if d2_c < 0:
d2=abs(d2_c)
dm2=abs(float(dati[5])) - d2
dm2_s= float(dm2) * 60
dm2_u="{:.3f}".format(dm2_s)
if d2 < 10 and d2 > -10:
lon_utile = '00'+str(d2)+str(dm2_u)
elif d2 < 100:
lon_utile = '0'+str(d2)+str(dm2_u)
else:
lon_utile = str(d2)+str(dm2_s)
lon_verso = 'W'
else:
d2=int(float(dati[5]))
dm2=float(dati[5]) - d2
dm2_s= float(dm2) * 60
dm2_u="{:.3f}".format(dm2_s)
if d2 < 10 and d2 > -10:
lon_utile = '00'+str(d2)+str(dm2_u)
elif d2 < 100:
lon_utile = '0'+str(d2)+str(dm2_u)
else:
lon_utile = str(d2)+str(dm2_u)
lon_verso = 'E'
rx_utile = dati[2][0:3]+'.'+dati[2][3:]
tx_utile = dati[3][0:3]+'.'+dati[3][3:]
AIS.sendall(str(dati[0])+">APRS,TCPIP*,qAC,"+str(self._CONFIG['APRS']['CALLSIGN'])+":!"+str(lat_utile)[:-2]+lat_verso+"/"+str(lon_utile)[:-1]+lon_verso+"r"+str(self._CONFIG['APRS']['MESSAGE'])+' RX: '+str(rx_utile)+' TX: '+str(tx_utile))
logging.info('APRS INVIATO')
if conta == 0:
if self._CONFIG['APRS']['REPORT_INTERVAL'] > 3:
l=task.LoopingCall(sendAprs)
l.start(float(int(self._CONFIG['APRS']['REPORT_INTERVAL']*60)))
else:
l=task.LoopingCall(sendAprs)
l.start(5*60)
logger.info('Report Time APRS to short')
else: else:
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr) self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
logger.warning('(%s) Peer info from Radio ID that has not logged in: %s', self._system, int_id(_peer_id)) logger.warning('(%s) Peer info from Radio ID that has not logged in: %s', self._system, int_id(_peer_id))
@ -768,6 +904,8 @@ if __name__ == '__main__':
import sys import sys
import os import os
import signal import signal
import aprslib
import threading
# Change the current directory to the location of the application # Change the current directory to the location of the application
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0]))) os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
@ -789,12 +927,12 @@ if __name__ == '__main__':
if cli_args.LOG_LEVEL: if cli_args.LOG_LEVEL:
CONFIG['LOGGER']['LOG_LEVEL'] = cli_args.LOG_LEVEL CONFIG['LOGGER']['LOG_LEVEL'] = cli_args.LOG_LEVEL
logger = log.config_logging(CONFIG['LOGGER']) logger = log.config_logging(CONFIG['LOGGER'])
logger.info('\n\nCopyright (c) 2013, 2014, 2015, 2016, 2018, 2019\n\tThe Regents of the K0USY Group. All rights reserved.\n') logger.info('APRS IMPLEMENTATION BY IU7IGU email: iu7igu@yahoo.com \n\nCopyright (c) 2013, 2014, 2015, 2016, 2018, 2019\n\tThe Regents of the K0USY Group. All rights reserved.')
logger.debug('(GLOBAL) Logging system started, anything from here on gets logged') logger.debug('(GLOBAL) Logging system started, anything from here on gets logged')
# Set up the signal handler # Set up the signal handler
def sig_handler(_signal, _frame): def sig_handler(_signal, _frame):
logger.info('(GLOBAL) SHUTDOWN: HBLINK IS TERMINATING WITH SIGNAL %s', str(_signal)) logger.info('(GLOBAL) SHUTDOWN: HBLINK IS TERMINATING WITH SIGNAL %s', str(_signal))
hblink_handler(_signal, _frame) hblink_handler(_signal, _frame)
logger.info('(GLOBAL) SHUTDOWN: ALL SYSTEM HANDLERS EXECUTED - STOPPING REACTOR') logger.info('(GLOBAL) SHUTDOWN: ALL SYSTEM HANDLERS EXECUTED - STOPPING REACTOR')
reactor.stop() reactor.stop()
@ -824,3 +962,4 @@ if __name__ == '__main__':
logger.debug('(GLOBAL) %s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system]) logger.debug('(GLOBAL) %s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system])
reactor.run() reactor.run()