hotspot APRS position, initial commit
This commit is contained in:
parent
09d88ed380
commit
19b32cfc67
35
bridge.py
35
bridge.py
|
|
@ -75,6 +75,8 @@ from socket import gethostbyname
|
||||||
from setproctitle import setproctitle
|
from setproctitle import setproctitle
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -430,6 +432,14 @@ def config_reports(_config, _factory):
|
||||||
reporting.start(_config['REPORTS']['REPORT_INTERVAL'])
|
reporting.start(_config['REPORTS']['REPORT_INTERVAL'])
|
||||||
|
|
||||||
return report_server
|
return report_server
|
||||||
|
# Send peer data that needs to be sent to APRS
|
||||||
|
def svrd_send_aprs_peer(_svrd_data):
|
||||||
|
_svrd_packet = SVRD
|
||||||
|
for system in CONFIG['SYSTEMS']:
|
||||||
|
if CONFIG['SYSTEMS'][system]['ENABLED']:
|
||||||
|
if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE':
|
||||||
|
if 'PEER_APRS' in CONFIG['SYSTEMS'][system]['OTHER_OPTIONS']:
|
||||||
|
systems[system].send_system(SVRD + b'APRS' + str.encode(str(_svrd_data)))
|
||||||
|
|
||||||
# Send data to all OBP connections that have an encryption key. Data such as subscribers are sent to other HBNet servers.
|
# Send data to all OBP connections that have an encryption key. Data such as subscribers are sent to other HBNet servers.
|
||||||
def svrd_send_all(_svrd_data):
|
def svrd_send_all(_svrd_data):
|
||||||
|
|
@ -445,8 +455,8 @@ def mirror_traffic(_data):
|
||||||
for system in CONFIG['SYSTEMS']:
|
for system in CONFIG['SYSTEMS']:
|
||||||
if CONFIG['SYSTEMS'][system]['ENABLED']:
|
if CONFIG['SYSTEMS'][system]['ENABLED']:
|
||||||
if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE':
|
if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE':
|
||||||
print(CONFIG['SYSTEMS'][system]['OTHER_OPTIONS'])
|
## print(CONFIG['SYSTEMS'][system]['OTHER_OPTIONS'])
|
||||||
if 'MIRROR_ALL_TRAFFIC' in CONFIG['SYSTEMS'][system]['OTHER_OPTIONS']:
|
if 'MIRROR_DATA' in CONFIG['SYSTEMS'][system]['OTHER_OPTIONS']:
|
||||||
systems[system].send_system(SVRD + b'MDAT' + _data)
|
systems[system].send_system(SVRD + b'MDAT' + _data)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -526,6 +536,7 @@ def ten_loop_func():
|
||||||
# Run this every minute for rule timer updates
|
# Run this every minute for rule timer updates
|
||||||
def rule_timer_loop(unit_flood_time):
|
def rule_timer_loop(unit_flood_time):
|
||||||
global UNIT_MAP
|
global UNIT_MAP
|
||||||
|
## print(HBSYSTEM('HOTSPOT', CONFIG, '')._peers)
|
||||||
logger.debug('(ROUTER) routerHBP Rule timer loop started')
|
logger.debug('(ROUTER) routerHBP Rule timer loop started')
|
||||||
_now = time()
|
_now = time()
|
||||||
#This is a good place to get and modify rules for users
|
#This is a good place to get and modify rules for users
|
||||||
|
|
@ -582,6 +593,17 @@ def rule_timer_loop(unit_flood_time):
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
report_server.send_clients(b'bridge updated')
|
report_server.send_clients(b'bridge updated')
|
||||||
|
|
||||||
|
# Send PEER info to data gateway for APRS packet generation
|
||||||
|
try:
|
||||||
|
for system in CONFIG['SYSTEMS']:
|
||||||
|
if CONFIG['SYSTEMS'][system]['ENABLED']:
|
||||||
|
if CONFIG['SYSTEMS'][system]['MODE'] == 'MASTER' or CONFIG['SYSTEMS'][system]['MODE'] == 'PROXY':
|
||||||
|
if CONFIG['SYSTEMS'][system]['STATIC_APRS_POSITION_ENABLED'] == True:
|
||||||
|
dict_data = ast.literal_eval(os.popen('cat /tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/' + system)).read())
|
||||||
|
svrd_send_aprs_peer(dict_data)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
|
|
||||||
# run this every 10 seconds to trim orphaned stream ids
|
# run this every 10 seconds to trim orphaned stream ids
|
||||||
def stream_trimmer_loop():
|
def stream_trimmer_loop():
|
||||||
|
|
@ -1593,6 +1615,7 @@ if __name__ == '__main__':
|
||||||
logger.info('(GLOBAL) SHUTDOWN: CONFBRIDGE IS TERMINATING WITH SIGNAL %s', str(_signal))
|
logger.info('(GLOBAL) SHUTDOWN: CONFBRIDGE 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')
|
||||||
|
os.popen('rm /tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/*'))
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
# Set signal handers so that we can gracefully exit if need be
|
# Set signal handers so that we can gracefully exit if need be
|
||||||
|
|
@ -1733,4 +1756,12 @@ if __name__ == '__main__':
|
||||||
## if LOCAL_CONFIG['WEB_SERVICE']['REMOTE_CONFIG_ENABLED']:
|
## if LOCAL_CONFIG['WEB_SERVICE']['REMOTE_CONFIG_ENABLED']:
|
||||||
## with open(CONFIG['WEB_SERVICE']['BURN_FILE'], 'w') as f:
|
## with open(CONFIG['WEB_SERVICE']['BURN_FILE'], 'w') as f:
|
||||||
## f.write(str(download_burnlist(CONFIG)))
|
## f.write(str(download_burnlist(CONFIG)))
|
||||||
|
|
||||||
|
# Create folder so hbnet.py can access list PEER connections
|
||||||
|
print(CONFIG['LOGGER']['LOG_NAME'])
|
||||||
|
if Path('/tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/')).exists():
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
Path('/tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/')).mkdir()
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,6 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
#### Modules for data gateway ###
|
#### Modules for data gateway ###
|
||||||
# modules from DATA_CONFIG.py
|
# modules from DATA_CONFIG.py
|
||||||
from bitarray import bitarray
|
|
||||||
from binascii import b2a_hex as ahex
|
from binascii import b2a_hex as ahex
|
||||||
import re
|
import re
|
||||||
##from binascii import a2b_hex as bhex
|
##from binascii import a2b_hex as bhex
|
||||||
|
|
@ -79,11 +78,6 @@ try:
|
||||||
import maidenhead as mh
|
import maidenhead as mh
|
||||||
except:
|
except:
|
||||||
logger.error('Error importing maidenhead module, make sure it is installed.')
|
logger.error('Error importing maidenhead module, make sure it is installed.')
|
||||||
# Module for sending email
|
|
||||||
try:
|
|
||||||
import smtplib
|
|
||||||
except:
|
|
||||||
logger.error('Error importing smtplib module, make sure it is installed.')
|
|
||||||
|
|
||||||
#Modules for APRS settings
|
#Modules for APRS settings
|
||||||
import ast
|
import ast
|
||||||
|
|
@ -134,6 +128,8 @@ packet_assembly = {}
|
||||||
|
|
||||||
pistar_overflow = 0.1
|
pistar_overflow = 0.1
|
||||||
|
|
||||||
|
peer_aprs = {}
|
||||||
|
|
||||||
# Keep track of what user needs which SMS format
|
# Keep track of what user needs which SMS format
|
||||||
|
|
||||||
def sms_type(sub, sms):
|
def sms_type(sub, sms):
|
||||||
|
|
@ -1645,6 +1641,8 @@ def aprs_beacon_send():
|
||||||
aprslib.parse(beacon_packet)
|
aprslib.parse(beacon_packet)
|
||||||
aprs_send(beacon_packet)
|
aprs_send(beacon_packet)
|
||||||
logger.debug(beacon_packet)
|
logger.debug(beacon_packet)
|
||||||
|
peer_aprs_packets()
|
||||||
|
logger.info('Uploaded PEER APRS positions')
|
||||||
|
|
||||||
##### DMR data function ####
|
##### DMR data function ####
|
||||||
def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data, mirror = False):
|
def data_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data, mirror = False):
|
||||||
|
|
@ -1965,7 +1963,42 @@ def rule_timer_loop():
|
||||||
logger.error('Send que error')
|
logger.error('Send que error')
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
|
||||||
|
def peer_aprs_packets():
|
||||||
|
for i in peer_aprs.items():
|
||||||
|
for h in i[1].items():
|
||||||
|
lat = decdeg2dms(float(h[1]['lat']))
|
||||||
|
lon = decdeg2dms(float(h[1]['lon']))
|
||||||
|
if lon[0] < 0:
|
||||||
|
lon_dir = 'W'
|
||||||
|
if lon[0] > 0:
|
||||||
|
lon_dir = 'E'
|
||||||
|
if lat[0] < 0:
|
||||||
|
lat_dir = 'S'
|
||||||
|
if lat[0] > 0:
|
||||||
|
lat_dir = 'N'
|
||||||
|
|
||||||
|
aprs_lat = str(str(re.sub('\..*|-', '', str(lat[0]))).zfill(2) + str(re.sub('\..*', '', str(lat[1])).zfill(2) + '.')) + str(re.sub('\..*', '', str(lat[2])).zfill(2)) + lat_dir
|
||||||
|
aprs_lon = str(str(re.sub('\..*|-', '', str(lon[0]))).zfill(3) + str(re.sub('\..*', '', str(lon[1])).zfill(2) + '.')) + str(re.sub('\..*', '', str(lon[2])).zfill(2)) + lon_dir
|
||||||
|
|
||||||
|
if len(str(h[0])) > 7:
|
||||||
|
ending = int(str(h[0])[-2:])
|
||||||
|
if ending in range(1, 25):
|
||||||
|
ssid = str(string.ascii_uppercase[ending - 1])
|
||||||
|
else:
|
||||||
|
ssid = 'A'
|
||||||
|
else:
|
||||||
|
ssid = 'A'
|
||||||
|
aprs_loc_packet = str(h[1]['call'] + '-' + ssid + '>APHBL3,TCPIP*:/' + str(datetime.datetime.utcnow().strftime("%H%M%Sh")) + str(aprs_lat) + '\\' + str(aprs_lon) + '&' + '/' + str(h[0]) + ' - ' + str(h[1]['description']))
|
||||||
|
logger.debug(aprs_loc_packet)
|
||||||
|
try:
|
||||||
|
aprslib.parse(aprs_loc_packet)
|
||||||
|
aprs_send(aprs_loc_packet)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
|
##
|
||||||
|
## print(lat)
|
||||||
|
#### print(lon)
|
||||||
|
|
||||||
class OBP(OPENBRIDGE):
|
class OBP(OPENBRIDGE):
|
||||||
|
|
||||||
|
|
@ -1995,8 +2028,14 @@ class OBP(OPENBRIDGE):
|
||||||
|
|
||||||
def svrd_received(self, _mode, _data):
|
def svrd_received(self, _mode, _data):
|
||||||
logger.debug('SVRD RCV')
|
logger.debug('SVRD RCV')
|
||||||
|
print(_mode)
|
||||||
if _mode == b'UNIT':
|
if _mode == b'UNIT':
|
||||||
UNIT_MAP[_data] = (self._system, time())
|
UNIT_MAP[_data] = (self._system, time())
|
||||||
|
if _mode == b'APRS':
|
||||||
|
## print(_data)
|
||||||
|
## print(self._system)
|
||||||
|
peer_aprs[self._system] = ast.literal_eval(_data.decode('utf-8'))
|
||||||
|
|
||||||
if _mode == b'DATA' or _mode == b'MDAT':
|
if _mode == b'DATA' or _mode == b'MDAT':
|
||||||
## print(ahex(_data))
|
## print(ahex(_data))
|
||||||
# DMR Data packet, sent via SVRD
|
# DMR Data packet, sent via SVRD
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ REPORT_CLIENTS: 127.0.0.1
|
||||||
LOG_FILE: /tmp/hblink.log
|
LOG_FILE: /tmp/hblink.log
|
||||||
LOG_HANDLERS: console-timed
|
LOG_HANDLERS: console-timed
|
||||||
LOG_LEVEL: DEBUG
|
LOG_LEVEL: DEBUG
|
||||||
|
# If running multiple HBNet servers on same host, LOG_NAME must be unique.
|
||||||
LOG_NAME: HBlink
|
LOG_NAME: HBlink
|
||||||
|
|
||||||
# DOWNLOAD AND IMPORT SUBSCRIBER, PEER and TGID ALIASES
|
# DOWNLOAD AND IMPORT SUBSCRIBER, PEER and TGID ALIASES
|
||||||
|
|
|
||||||
30
hblink.py
30
hblink.py
|
|
@ -66,6 +66,9 @@ import re
|
||||||
# Encryption library
|
# Encryption library
|
||||||
from cryptography.fernet import Fernet
|
from cryptography.fernet import Fernet
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||||
|
|
@ -91,6 +94,17 @@ def decrypt_packet(key, message):
|
||||||
|
|
||||||
return token
|
return token
|
||||||
|
|
||||||
|
def write_peer_file(master, peer_dict, CONFIG):
|
||||||
|
# Pull stuff for aprs out
|
||||||
|
print(peer_dict)
|
||||||
|
new_peers = {}
|
||||||
|
for d in peer_dict.items():
|
||||||
|
print(d[1])
|
||||||
|
new_peers[int_id(d[0])] = {'call': str(d[1]['CALLSIGN'].decode('utf-8')).strip(' '), 'lat':str(d[1]['LATITUDE'].decode('utf-8')), 'lon':str(d[1]['LONGITUDE'].decode('utf-8')), 'description':str(d[1]['DESCRIPTION'].decode('utf-8'))}
|
||||||
|
with open('/tmp/' + CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/' + master, 'w') as peer_file:
|
||||||
|
peer_file.write(str(new_peers))
|
||||||
|
peer_file.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):
|
||||||
|
|
@ -280,6 +294,7 @@ class OPENBRIDGE(DatagramProtocol):
|
||||||
|
|
||||||
class HBSYSTEM(DatagramProtocol):
|
class HBSYSTEM(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
|
||||||
self._CONFIG = _config
|
self._CONFIG = _config
|
||||||
self._system = _name
|
self._system = _name
|
||||||
|
|
@ -434,6 +449,7 @@ class HBSYSTEM(DatagramProtocol):
|
||||||
|
|
||||||
# Aliased in __init__ to maintenance_loop if system is a master
|
# Aliased in __init__ to maintenance_loop if system is a master
|
||||||
def master_maintenance_loop(self):
|
def master_maintenance_loop(self):
|
||||||
|
print(self._peers)
|
||||||
logger.debug('(%s) Master maintenance loop started', self._system)
|
logger.debug('(%s) Master maintenance loop started', self._system)
|
||||||
remove_list = []
|
remove_list = []
|
||||||
for peer in self._peers:
|
for peer in self._peers:
|
||||||
|
|
@ -724,6 +740,8 @@ class HBSYSTEM(DatagramProtocol):
|
||||||
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
|
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
|
||||||
self.send_peer_loc(_peer_id, self._peers[_peer_id]['CALLSIGN'], '*', '*', '*', '*', '*', '*')
|
self.send_peer_loc(_peer_id, self._peers[_peer_id]['CALLSIGN'], '*', '*', '*', '*', '*', '*')
|
||||||
del self._peers[_peer_id]
|
del self._peers[_peer_id]
|
||||||
|
#open, remove, and write change
|
||||||
|
write_peer_file(self._system, self._peers, self._CONFIG)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
_peer_id = _data[4:8] # Configure Command
|
_peer_id = _data[4:8] # Configure Command
|
||||||
|
|
@ -751,11 +769,14 @@ 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'])
|
||||||
|
|
||||||
if 'NO_MAP' in str(_this_peer['LOCATION']):
|
if 'NO_MAP' in str(_this_peer['LOCATION']):
|
||||||
self.send_peer_loc(_peer_id, self._peers[_peer_id]['CALLSIGN'], '*', '*', '*', '*', '*', '*')
|
self.send_peer_loc(_peer_id, self._peers[_peer_id]['CALLSIGN'], '*', '*', '*', '*', '*', '*')
|
||||||
## print(_this_peer['LOCATION'])
|
## print(_this_peer['LOCATION'])
|
||||||
## pass
|
## pass
|
||||||
else:
|
else:
|
||||||
|
# Function to open and write dict here
|
||||||
|
write_peer_file(self._system, self._peers, self._CONFIG)
|
||||||
self.send_peer_loc(_peer_id, _this_peer['CALLSIGN'], _this_peer['LATITUDE'], _this_peer['LONGITUDE'], _this_peer['URL'], _this_peer['DESCRIPTION'], _this_peer['LOCATION'], str(_this_peer['PACKAGE_ID']) + ' - ' + str(_this_peer['SOFTWARE_ID']))
|
self.send_peer_loc(_peer_id, _this_peer['CALLSIGN'], _this_peer['LATITUDE'], _this_peer['LONGITUDE'], _this_peer['URL'], _this_peer['DESCRIPTION'], _this_peer['LOCATION'], str(_this_peer['PACKAGE_ID']) + ' - ' + str(_this_peer['SOFTWARE_ID']))
|
||||||
else:
|
else:
|
||||||
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
|
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
|
||||||
|
|
@ -784,6 +805,8 @@ class HBSYSTEM(DatagramProtocol):
|
||||||
## self.mmdvm_cmd(_data)
|
## self.mmdvm_cmd(_data)
|
||||||
if 'NO_MAP' in str(_data[8:]):
|
if 'NO_MAP' in str(_data[8:]):
|
||||||
self.send_peer_loc(_peer_id, self._peers[_peer_id]['CALLSIGN'], '*', '*', '*', '*', '*', '*')
|
self.send_peer_loc(_peer_id, self._peers[_peer_id]['CALLSIGN'], '*', '*', '*', '*', '*', '*')
|
||||||
|
elif 'NO_MAP' not in str(_data[8:]):
|
||||||
|
write_peer_file(self._system, self._peers, self._CONFIG)
|
||||||
self.transport.write(b''.join([RPTACK, _peer_id]), _sockaddr)
|
self.transport.write(b''.join([RPTACK, _peer_id]), _sockaddr)
|
||||||
|
|
||||||
elif _command == DMRA:
|
elif _command == DMRA:
|
||||||
|
|
@ -1073,6 +1096,7 @@ if __name__ == '__main__':
|
||||||
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')
|
||||||
|
os.popen('rm /tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/*'))
|
||||||
reactor.stop()
|
reactor.stop()
|
||||||
|
|
||||||
# Set signal handers so that we can gracefully exit if need be
|
# Set signal handers so that we can gracefully exit if need be
|
||||||
|
|
@ -1104,4 +1128,10 @@ if __name__ == '__main__':
|
||||||
with open(CONFIG['WEB_SERVICE']['BURN_FILE'], 'w') as f:
|
with open(CONFIG['WEB_SERVICE']['BURN_FILE'], 'w') as f:
|
||||||
f.write(str(download_burnlist(CONFIG)))
|
f.write(str(download_burnlist(CONFIG)))
|
||||||
|
|
||||||
|
# Create folder so hbnet.py can access list PEER connections
|
||||||
|
if Path('/tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/')).exists():
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
Path('/tmp/' + (CONFIG['LOGGER']['LOG_NAME'] + '_PEERS/')).mkdir()
|
||||||
|
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue