Compare commits
2 Commits
gps
...
trimmed-do
Author | SHA1 | Date | |
---|---|---|---|
|
06514567ef | ||
|
3ee762475e |
127
hblink.py
127
hblink.py
@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2019 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
# Copyright (C) 2016-2020 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@ -45,11 +45,7 @@ from twisted.internet import reactor, task
|
||||
import log
|
||||
import config
|
||||
from const import *
|
||||
from dmr_utils3.utils import int_id, bytes_4, try_download, mk_id_dict
|
||||
|
||||
# Imports for the reporting server
|
||||
import pickle
|
||||
from reporting_const import *
|
||||
from dmr_utils3.utils import int_id, bytes_4
|
||||
|
||||
# The module needs logging logging, but handlers, etc. are controlled by the parent
|
||||
import logging
|
||||
@ -66,23 +62,6 @@ __email__ = 'n0mjs@me.com'
|
||||
# Global variables used whether we are a module or __main__
|
||||
systems = {}
|
||||
|
||||
# Timed loop used for reporting HBP status
|
||||
def config_reports(_config, _factory):
|
||||
def reporting_loop(_logger, _server):
|
||||
_logger.debug('(GLOBAL) Periodic reporting loop started')
|
||||
_server.send_config()
|
||||
|
||||
logger.info('(GLOBAL) HBlink TCP reporting server configured')
|
||||
|
||||
report_server = _factory(_config)
|
||||
report_server.clients = []
|
||||
reactor.listenTCP(_config['REPORTS']['REPORT_PORT'], report_server)
|
||||
|
||||
reporting = task.LoopingCall(reporting_loop, logger, report_server)
|
||||
reporting.start(_config['REPORTS']['REPORT_INTERVAL'])
|
||||
|
||||
return report_server
|
||||
|
||||
|
||||
# Shut ourselves down gracefully by disconnecting from the masters and peers.
|
||||
def hblink_handler(_signal, _frame):
|
||||
@ -105,11 +84,10 @@ def acl_check(_id, _acl):
|
||||
#************************************************
|
||||
|
||||
class OPENBRIDGE(DatagramProtocol):
|
||||
def __init__(self, _name, _config, _report):
|
||||
def __init__(self, _name, _config):
|
||||
# Define a few shortcuts to make the rest of the class more readable
|
||||
self._CONFIG = _config
|
||||
self._system = _name
|
||||
self._report = _report
|
||||
self._config = self._CONFIG['SYSTEMS'][self._system]
|
||||
self._laststrid = deque([], 20)
|
||||
|
||||
@ -200,11 +178,10 @@ class OPENBRIDGE(DatagramProtocol):
|
||||
#************************************************
|
||||
|
||||
class HBSYSTEM(DatagramProtocol):
|
||||
def __init__(self, _name, _config, _report):
|
||||
def __init__(self, _name, _config):
|
||||
# Define a few shortcuts to make the rest of the class more readable
|
||||
self._CONFIG = _config
|
||||
self._system = _name
|
||||
self._report = _report
|
||||
self._config = self._CONFIG['SYSTEMS'][self._system]
|
||||
self._laststrid = {1: b'', 2: b''}
|
||||
|
||||
@ -272,19 +249,20 @@ class HBSYSTEM(DatagramProtocol):
|
||||
if _packet[:4] == DMRD:
|
||||
_packet = b''.join([_packet[:11], _peer, _packet[15:]])
|
||||
self.transport.write(_packet, self._peers[_peer]['SOCKADDR'])
|
||||
# KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!!
|
||||
#logger.debug('(%s) TX Packet to %s on port %s: %s', self._peers[_peer]['RADIO_ID'], self._peers[_peer]['IP'], self._peers[_peer]['PORT'], ahex(_packet))
|
||||
|
||||
def send_master(self, _packet):
|
||||
if _packet[:4] == DMRD:
|
||||
_packet = b''.join([_packet[:11], self._config['RADIO_ID'], _packet[15:]])
|
||||
self.transport.write(_packet, self._config['MASTER_SOCKADDR'])
|
||||
# KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!!
|
||||
# logger.debug('(%s) TX Packet to %s:%s -- %s', self._system, self._config['MASTER_IP'], self._config['MASTER_PORT'], ahex(_packet))
|
||||
|
||||
def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data):
|
||||
pass
|
||||
|
||||
def dmra_recieved(self, _data):
|
||||
pass
|
||||
|
||||
def master_dereg(self):
|
||||
for _peer in self._peers:
|
||||
self.send_peer(_peer, MSTCL + _peer)
|
||||
@ -296,7 +274,6 @@ class HBSYSTEM(DatagramProtocol):
|
||||
|
||||
# Aliased in __init__ to datagramReceived if system is a master
|
||||
def master_datagramReceived(self, _data, _sockaddr):
|
||||
# Keep This Line Commented Unless HEAVILY Debugging!
|
||||
# logger.debug('(%s) RX packet from %s -- %s', self._system, _sockaddr, ahex(_data))
|
||||
|
||||
# Extract the command, which is various length, all but one 4 significant characters -- RPTCL
|
||||
@ -489,6 +466,12 @@ class HBSYSTEM(DatagramProtocol):
|
||||
self.transport.write(b''.join([MSTNAK, _peer_id]), _sockaddr)
|
||||
logger.warning('(%s) Ping from Radio ID that is not logged in: %s', self._system, int_id(_peer_id))
|
||||
|
||||
# Talker alias callback
|
||||
elif _command == DMRA:
|
||||
self.dmrd_received(_data)
|
||||
#logger.info('(%s) DMRA recieved', self._system)
|
||||
|
||||
|
||||
else:
|
||||
logger.error('(%s) Unrecognized command. Raw HBP PDU: %s', self._system, ahex(_data))
|
||||
|
||||
@ -651,78 +634,6 @@ class HBSYSTEM(DatagramProtocol):
|
||||
else:
|
||||
logger.error('(%s) Received an invalid command in packet: %s', self._system, ahex(_data))
|
||||
|
||||
#
|
||||
# Socket-based reporting section
|
||||
#
|
||||
class report(NetstringReceiver):
|
||||
def __init__(self, factory):
|
||||
self._factory = factory
|
||||
|
||||
def connectionMade(self):
|
||||
self._factory.clients.append(self)
|
||||
logger.info('(REPORT) HBlink reporting client connected: %s', self.transport.getPeer())
|
||||
|
||||
def connectionLost(self, reason):
|
||||
logger.info('(REPORT) HBlink reporting client disconnected: %s', self.transport.getPeer())
|
||||
self._factory.clients.remove(self)
|
||||
|
||||
def stringReceived(self, data):
|
||||
self.process_message(data)
|
||||
|
||||
def process_message(self, _message):
|
||||
opcode = _message[:1]
|
||||
if opcode == REPORT_OPCODES['CONFIG_REQ']:
|
||||
logger.info('(REPORT) HBlink reporting client sent \'CONFIG_REQ\': %s', self.transport.getPeer())
|
||||
self.send_config()
|
||||
else:
|
||||
logger.error('(REPORT) got unknown opcode')
|
||||
|
||||
class reportFactory(Factory):
|
||||
def __init__(self, config):
|
||||
self._config = config
|
||||
|
||||
def buildProtocol(self, addr):
|
||||
if (addr.host) in self._config['REPORTS']['REPORT_CLIENTS'] or '*' in self._config['REPORTS']['REPORT_CLIENTS']:
|
||||
logger.debug('(REPORT) Permitting report server connection attempt from: %s:%s', addr.host, addr.port)
|
||||
return report(self)
|
||||
else:
|
||||
logger.error('(REPORT) Invalid report server connection attempt from: %s:%s', addr.host, addr.port)
|
||||
return None
|
||||
|
||||
def send_clients(self, _message):
|
||||
for client in self.clients:
|
||||
client.sendString(_message)
|
||||
|
||||
def send_config(self):
|
||||
serialized = pickle.dumps(self._config['SYSTEMS'], protocol=2) #.decode('utf-8', errors='ignore') #pickle.HIGHEST_PROTOCOL)
|
||||
self.send_clients(b''.join([REPORT_OPCODES['CONFIG_SND'], serialized]))
|
||||
|
||||
|
||||
# ID ALIAS CREATION
|
||||
# Download
|
||||
def mk_aliases(_config):
|
||||
if _config['ALIASES']['TRY_DOWNLOAD'] == True:
|
||||
# Try updating peer aliases file
|
||||
result = try_download(_config['ALIASES']['PATH'], _config['ALIASES']['PEER_FILE'], _config['ALIASES']['PEER_URL'], _config['ALIASES']['STALE_TIME'])
|
||||
logger.info('(GLOBAL) %s', result)
|
||||
# Try updating subscriber aliases file
|
||||
result = try_download(_config['ALIASES']['PATH'], _config['ALIASES']['SUBSCRIBER_FILE'], _config['ALIASES']['SUBSCRIBER_URL'], _config['ALIASES']['STALE_TIME'])
|
||||
logger.info('(GLOBAL) %s', result)
|
||||
|
||||
# Make Dictionaries
|
||||
peer_ids = mk_id_dict(_config['ALIASES']['PATH'], _config['ALIASES']['PEER_FILE'])
|
||||
if peer_ids:
|
||||
logger.info('(GLOBAL) ID ALIAS MAPPER: peer_ids dictionary is available')
|
||||
|
||||
subscriber_ids = mk_id_dict(_config['ALIASES']['PATH'], _config['ALIASES']['SUBSCRIBER_FILE'])
|
||||
if subscriber_ids:
|
||||
logger.info('(GLOBAL) ID ALIAS MAPPER: subscriber_ids dictionary is available')
|
||||
|
||||
talkgroup_ids = mk_id_dict(_config['ALIASES']['PATH'], _config['ALIASES']['TGID_FILE'])
|
||||
if talkgroup_ids:
|
||||
logger.info('(GLOBAL) ID ALIAS MAPPER: talkgroup_ids dictionary is available')
|
||||
|
||||
return peer_ids, subscriber_ids, talkgroup_ids
|
||||
|
||||
#************************************************
|
||||
# MAIN PROGRAM LOOP STARTS HERE
|
||||
@ -769,23 +680,15 @@ if __name__ == '__main__':
|
||||
for sig in [signal.SIGTERM, signal.SIGINT]:
|
||||
signal.signal(sig, sig_handler)
|
||||
|
||||
peer_ids, subscriber_ids, talkgroup_ids = mk_aliases(CONFIG)
|
||||
|
||||
# INITIALIZE THE REPORTING LOOP
|
||||
if CONFIG['REPORTS']['REPORT']:
|
||||
report_server = config_reports(CONFIG, reportFactory)
|
||||
else:
|
||||
report_server = None
|
||||
logger.info('(REPORT) TCP Socket reporting not configured')
|
||||
|
||||
# HBlink instance creation
|
||||
logger.info('(GLOBAL) HBlink \'HBlink.py\' -- SYSTEM STARTING...')
|
||||
for system in CONFIG['SYSTEMS']:
|
||||
if CONFIG['SYSTEMS'][system]['ENABLED']:
|
||||
if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE':
|
||||
systems[system] = OPENBRIDGE(system, CONFIG, report_server)
|
||||
systems[system] = OPENBRIDGE(system, CONFIG)
|
||||
else:
|
||||
systems[system] = HBSYSTEM(system, CONFIG, report_server)
|
||||
systems[system] = HBSYSTEM(system, CONFIG)
|
||||
reactor.listenUDP(CONFIG['SYSTEMS'][system]['PORT'], systems[system], interface=CONFIG['SYSTEMS'][system]['IP'])
|
||||
logger.debug('(GLOBAL) %s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system])
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user