Compare commits
	
		
			2 Commits
		
	
	
		
			gps
			...
			trimmed-do
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 06514567ef | ||
|  | 3ee762475e | 
							
								
								
									
										129
									
								
								hblink.py
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								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,18 +249,19 @@ 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: | ||||
| @ -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)) | ||||
| 
 | ||||
| @ -650,79 +633,7 @@ 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user