Merge branch 'master' of https://github.com/n0mjs710/hblink3
This commit is contained in:
		
						commit
						a16e426c55
					
				
							
								
								
									
										0
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										30
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -1,30 +0,0 @@ | |||||||
| FROM python:3.7-slim-stretch |  | ||||||
| 
 |  | ||||||
| RUN apt update && \ |  | ||||||
|     apt install -y git && \ |  | ||||||
|     cd /usr/src/ && \ |  | ||||||
|     git clone https://github.com/n0mjs710/dmr_utils3 && \ |  | ||||||
|     cd /usr/src/dmr_utils3 && \ |  | ||||||
|     ./install.sh && \ |  | ||||||
|     rm -rf /var/lib/apt/lists/* && \ |  | ||||||
|     cd /opt && \ |  | ||||||
|     rm -rf /usr/src/dmr_utils3 && \ |  | ||||||
|     git clone https://github.com/n0mjs710/hblink3 |  | ||||||
| ENV AAA BBBB |  | ||||||
| RUN cd /opt/hblink3/ && \ |  | ||||||
|     sed -i s/.*python.*//g  requirements.txt && \ |  | ||||||
|     pip install --no-cache-dir -r requirements.txt |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ADD entrypoint /entrypoint |  | ||||||
| 
 |  | ||||||
| RUN adduser -u 54000 radio && \ |  | ||||||
|     adduser radio radio && \ |  | ||||||
|     chmod 755 /entrypoint && \ |  | ||||||
|     chown radio:radio /entrypoint && \ |  | ||||||
|     chown radio /opt/hblink3 |  | ||||||
| 
 |  | ||||||
| USER radio  |  | ||||||
| EXPOSE 54000 |  | ||||||
| 
 |  | ||||||
| ENTRYPOINT [ "/entrypoint" ] |  | ||||||
							
								
								
									
										150
									
								
								app_template.py
									
									
									
									
									
								
							
							
						
						
									
										150
									
								
								app_template.py
									
									
									
									
									
								
							| @ -1,150 +0,0 @@ | |||||||
| #!/usr/bin/env python |  | ||||||
| # |  | ||||||
| ############################################################################### |  | ||||||
| #   Copyright (C) 2016-2019 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 |  | ||||||
| #   the Free Software Foundation; either version 3 of the License, or |  | ||||||
| #   (at your option) any later version. |  | ||||||
| # |  | ||||||
| #   This program is distributed in the hope that it will be useful, |  | ||||||
| #   but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
| #   GNU General Public License for more details. |  | ||||||
| # |  | ||||||
| #   You should have received a copy of the GNU General Public License |  | ||||||
| #   along with this program; if not, write to the Free Software Foundation, |  | ||||||
| #   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA |  | ||||||
| ############################################################################### |  | ||||||
| 
 |  | ||||||
| # Python modules we need |  | ||||||
| import sys |  | ||||||
| from bitarray import bitarray |  | ||||||
| from time import time |  | ||||||
| from importlib import import_module |  | ||||||
| 
 |  | ||||||
| # Twisted is pretty important, so I keep it separate |  | ||||||
| from twisted.internet.protocol import Factory, Protocol |  | ||||||
| from twisted.protocols.basic import NetstringReceiver |  | ||||||
| from twisted.internet import reactor, task |  | ||||||
| 
 |  | ||||||
| # Things we import from the main hblink module |  | ||||||
| from hblink import HBSYSTEM, OPENBRIDGE, systems, hblink_handler, reportFactory, REPORT_OPCODES, mk_aliases |  | ||||||
| from dmr_utils3.utils import bytes_3, int_id, get_alias |  | ||||||
| from dmr_utils3 import decode, bptc, const |  | ||||||
| import config |  | ||||||
| import log |  | ||||||
| from const import * |  | ||||||
| 
 |  | ||||||
| # Stuff for socket reporting |  | ||||||
| import pickle |  | ||||||
| # REMOVE LATER from datetime import datetime |  | ||||||
| # The module needs logging, but handlers, etc. are controlled by the parent |  | ||||||
| import logging |  | ||||||
| logger = logging.getLogger(__name__) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Does anybody read this stuff? There's a PEP somewhere that says I should do this. |  | ||||||
| __author__     = 'Cortney T. Buffington, N0MJS' |  | ||||||
| __copyright__  = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group' |  | ||||||
| __credits__    = 'Colin Durbridge, G4EML, Steve Zingman, N4IRS; Mike Zingman, N4IRR; Jonathan Naylor, G4KLX; Hans Barthen, DL5DI; Torsten Shultze, DG1HT' |  | ||||||
| __license__    = 'GNU GPLv3' |  | ||||||
| __maintainer__ = 'Cort Buffington, N0MJS' |  | ||||||
| __email__      = 'n0mjs@me.com' |  | ||||||
| 
 |  | ||||||
| # Module gobal varaibles |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class OBP(OPENBRIDGE): |  | ||||||
| 
 |  | ||||||
|     def __init__(self, _name, _config, _report): |  | ||||||
|         OPENBRIDGE.__init__(self, _name, _config, _report) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class HBP(HBSYSTEM): |  | ||||||
| 
 |  | ||||||
|     def __init__(self, _name, _config, _report): |  | ||||||
|         HBSYSTEM.__init__(self, _name, _config, _report) |  | ||||||
| 
 |  | ||||||
|     def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #************************************************ |  | ||||||
| #      MAIN PROGRAM LOOP STARTS HERE |  | ||||||
| #************************************************ |  | ||||||
| 
 |  | ||||||
| if __name__ == '__main__': |  | ||||||
| 
 |  | ||||||
|     import argparse |  | ||||||
|     import sys |  | ||||||
|     import os |  | ||||||
|     import signal |  | ||||||
| 
 |  | ||||||
|     # Change the current directory to the location of the application |  | ||||||
|     os.chdir(os.path.dirname(os.path.realpath(sys.argv[0]))) |  | ||||||
| 
 |  | ||||||
|     # CLI argument parser - handles picking up the config file from the command line, and sending a "help" message |  | ||||||
|     parser = argparse.ArgumentParser() |  | ||||||
|     parser.add_argument('-c', '--config', action='store', dest='CONFIG_FILE', help='/full/path/to/config.file (usually hblink.cfg)') |  | ||||||
|     parser.add_argument('-l', '--logging', action='store', dest='LOG_LEVEL', help='Override config file logging level.') |  | ||||||
|     cli_args = parser.parse_args() |  | ||||||
| 
 |  | ||||||
|     # Ensure we have a path for the config file, if one wasn't specified, then use the default (top of file) |  | ||||||
|     if not cli_args.CONFIG_FILE: |  | ||||||
|         cli_args.CONFIG_FILE = os.path.dirname(os.path.abspath(__file__))+'/hblink.cfg' |  | ||||||
| 
 |  | ||||||
|     # Call the external routine to build the configuration dictionary |  | ||||||
|     CONFIG = config.build_config(cli_args.CONFIG_FILE) |  | ||||||
| 
 |  | ||||||
|     # Start the system logger |  | ||||||
|     if cli_args.LOG_LEVEL: |  | ||||||
|         CONFIG['LOGGER']['LOG_LEVEL'] = cli_args.LOG_LEVEL |  | ||||||
|     logger = log.config_logging(CONFIG['LOGGER']) |  | ||||||
|     logger.info('\n\nCopyright (c) 2013, 2014, 2015, 2016, 2018\n\tThe Regents of the K0USY Group. All rights reserved.\n') |  | ||||||
|     logger.debug('(GLOBAL) Logging system started, anything from here on gets logged') |  | ||||||
| 
 |  | ||||||
|     # Set up the signal handler |  | ||||||
|     def sig_handler(_signal, _frame): |  | ||||||
|         logger.info('(GLOBAL) SHUTDOWN: CONFBRIDGE IS TERMINATING WITH SIGNAL %s', str(_signal)) |  | ||||||
|         hblink_handler(_signal, _frame) |  | ||||||
|         logger.info('(GLOBAL) SHUTDOWN: ALL SYSTEM HANDLERS EXECUTED - STOPPING REACTOR') |  | ||||||
|         reactor.stop() |  | ||||||
| 
 |  | ||||||
|     # Set signal handers so that we can gracefully exit if need be |  | ||||||
|     for sig in [signal.SIGINT, signal.SIGTERM]: |  | ||||||
|         signal.signal(sig, sig_handler) |  | ||||||
| 
 |  | ||||||
|     # Create the name-number mapping dictionaries |  | ||||||
|     peer_ids, subscriber_ids, talkgroup_ids = mk_aliases(CONFIG) |  | ||||||
| 
 |  | ||||||
|     # INITIALIZE THE REPORTING LOOP |  | ||||||
|     if CONFIG['REPORTS']['REPORT']: |  | ||||||
|         report_server = config_reports(CONFIG, bridgeReportFactory) |  | ||||||
|     else: |  | ||||||
|         report_server = None |  | ||||||
|         logger.info('(REPORT) TCP Socket reporting not configured') |  | ||||||
| 
 |  | ||||||
|     # HBlink instance creation |  | ||||||
|     logger.info('(GLOBAL) HBlink \'bridge.py\' -- SYSTEM STARTING...') |  | ||||||
|     for system in CONFIG['SYSTEMS']: |  | ||||||
|         if CONFIG['SYSTEMS'][system]['ENABLED']: |  | ||||||
|             if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE': |  | ||||||
|                 systems[system] = OBP(system, CONFIG, report_server) |  | ||||||
|             else: |  | ||||||
|                 systems[system] = HBP(system, CONFIG, report_server) |  | ||||||
|             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]) |  | ||||||
| 
 |  | ||||||
|     def loopingErrHandle(failure): |  | ||||||
|         logger.error('(GLOBAL) STOPPING REACTOR TO AVOID MEMORY LEAK: Unhandled error in timed loop.\n %s', failure) |  | ||||||
|         reactor.stop() |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     reactor.run() |  | ||||||
							
								
								
									
										143
									
								
								blank_app.py
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								blank_app.py
									
									
									
									
									
								
							| @ -1,143 +0,0 @@ | |||||||
| #!/usr/bin/env python |  | ||||||
| # |  | ||||||
| ############################################################################### |  | ||||||
| #   Copyright (C) 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 |  | ||||||
| #   the Free Software Foundation; either version 3 of the License, or |  | ||||||
| #   (at your option) any later version. |  | ||||||
| # |  | ||||||
| #   This program is distributed in the hope that it will be useful, |  | ||||||
| #   but WITHOUT ANY WARRANTY; without even the implied warranty of |  | ||||||
| #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | ||||||
| #   GNU General Public License for more details. |  | ||||||
| # |  | ||||||
| #   You should have received a copy of the GNU General Public License |  | ||||||
| #   along with this program; if not, write to the Free Software Foundation, |  | ||||||
| #   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA |  | ||||||
| ############################################################################### |  | ||||||
| 
 |  | ||||||
| ''' |  | ||||||
| This is a blank application template to build on top of hblink.py. It contains |  | ||||||
| only the things you need to, essentially, run hblink.py underneath and do nothing |  | ||||||
| else. The expected behaviour is to override the dmrd_received function from |  | ||||||
| hblink.py to do somethign meaningful, so that framework is completed, but as |  | ||||||
| it stands, still does nothing with the DMRD packet. |  | ||||||
| ''' |  | ||||||
| 
 |  | ||||||
| # Python modules we need |  | ||||||
| import sys |  | ||||||
| from bitarray import bitarray |  | ||||||
| from time import time |  | ||||||
| from importlib import import_module |  | ||||||
| from types import ModuleType |  | ||||||
| 
 |  | ||||||
| # Twisted is pretty important, so I keep it separate |  | ||||||
| from twisted.internet.protocol import Factory, Protocol |  | ||||||
| from twisted.protocols.basic import NetstringReceiver |  | ||||||
| from twisted.internet import reactor, task |  | ||||||
| 
 |  | ||||||
| # Things we import from the main hblink module |  | ||||||
| from hblink import HBSYSTEM, OPENBRIDGE, systems, hblink_handler, reportFactory, REPORT_OPCODES, config_reports, mk_aliases, acl_check |  | ||||||
| from dmr_utils3.utils import bytes_3, int_id, get_alias |  | ||||||
| from dmr_utils3 import decode, bptc, const |  | ||||||
| import config |  | ||||||
| import log |  | ||||||
| import const |  | ||||||
| 
 |  | ||||||
| # The module needs logging logging, but handlers, etc. are controlled by the parent |  | ||||||
| import logging |  | ||||||
| logger = logging.getLogger(__name__) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| # Does anybody read this stuff? There's a PEP somewhere that says I should do this. |  | ||||||
| __author__     = 'Cortney T. Buffington, N0MJS' |  | ||||||
| __copyright__  = 'Copyright (c) 2020 Cortney T. Buffington' |  | ||||||
| __credits__    = 'Colin Durbridge, G4EML, Steve Zingman, N4IRS; Mike Zingman, N4IRR; Jonathan Naylor, G4KLX; Hans Barthen, DL5DI; Torsten Shultze, DG1HT' |  | ||||||
| __license__    = 'GNU GPLv3' |  | ||||||
| __maintainer__ = 'Cort Buffington, N0MJS' |  | ||||||
| __email__      = 'n0mjs@me.com' |  | ||||||
| __status__     = 'pre-alpha' |  | ||||||
| 
 |  | ||||||
| # Module gobal varaibles |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class blankSYSTEM(HBSYSTEM): |  | ||||||
| 
 |  | ||||||
|     def __init__(self, _name, _config, _report): |  | ||||||
|         HBSYSTEM.__init__(self, _name, _config, _report) |  | ||||||
| 
 |  | ||||||
|     def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| #************************************************ |  | ||||||
| #      MAIN PROGRAM LOOP STARTS HERE |  | ||||||
| #************************************************ |  | ||||||
| 
 |  | ||||||
| if __name__ == '__main__': |  | ||||||
|     import argparse |  | ||||||
|     import sys |  | ||||||
|     import os |  | ||||||
|     import signal |  | ||||||
|     from dmr_utils3.utils import try_download, mk_id_dict |  | ||||||
| 
 |  | ||||||
|     # Change the current directory to the location of the application |  | ||||||
|     os.chdir(os.path.dirname(os.path.realpath(sys.argv[0]))) |  | ||||||
| 
 |  | ||||||
|     # CLI argument parser - handles picking up the config file from the command line, and sending a "help" message |  | ||||||
|     parser = argparse.ArgumentParser() |  | ||||||
|     parser.add_argument('-c', '--config', action='store', dest='CONFIG_FILE', help='/full/path/to/config.file (usually hblink.cfg)') |  | ||||||
|     parser.add_argument('-l', '--logging', action='store', dest='LOG_LEVEL', help='Override config file logging level.') |  | ||||||
|     cli_args = parser.parse_args() |  | ||||||
| 
 |  | ||||||
|     # Ensure we have a path for the config file, if one wasn't specified, then use the default (top of file) |  | ||||||
|     if not cli_args.CONFIG_FILE: |  | ||||||
|         cli_args.CONFIG_FILE = os.path.dirname(os.path.abspath(__file__))+'/hblink.cfg' |  | ||||||
| 
 |  | ||||||
|     # Call the external routine to build the configuration dictionary |  | ||||||
|     CONFIG = config.build_config(cli_args.CONFIG_FILE) |  | ||||||
| 
 |  | ||||||
|     # Start the system logger |  | ||||||
|     if cli_args.LOG_LEVEL: |  | ||||||
|         CONFIG['LOGGER']['LOG_LEVEL'] = cli_args.LOG_LEVEL |  | ||||||
|     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.debug('Logging system started, anything from here on gets logged') |  | ||||||
| 
 |  | ||||||
|     # Set up the signal handler |  | ||||||
|     def sig_handler(_signal, _frame): |  | ||||||
|         logger.info('SHUTDOWN: >>>BLANK APP<<< IS TERMINATING WITH SIGNAL %s', str(_signal)) |  | ||||||
|         hblink_handler(_signal, _frame) |  | ||||||
|         logger.info('SHUTDOWN: ALL SYSTEM HANDLERS EXECUTED - STOPPING REACTOR') |  | ||||||
|         reactor.stop() |  | ||||||
| 
 |  | ||||||
|     # Set signal handers so that we can gracefully exit if need be |  | ||||||
|     for sig in [signal.SIGTERM, signal.SIGINT]: |  | ||||||
|         signal.signal(sig, sig_handler) |  | ||||||
| 
 |  | ||||||
|     # Create the name-number mapping dictionaries |  | ||||||
|     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('HBlink \'blank_app.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) |  | ||||||
|             else: |  | ||||||
|                 systems[system] = HBSYSTEM(system, CONFIG, report_server) |  | ||||||
|                  |  | ||||||
|             reactor.listenUDP(CONFIG['SYSTEMS'][system]['PORT'], systems[system], interface=CONFIG['SYSTEMS'][system]['IP']) |  | ||||||
|             logger.debug('%s instance created: %s, %s', CONFIG['SYSTEMS'][system]['MODE'], system, systems[system]) |  | ||||||
| 
 |  | ||||||
|     reactor.run() |  | ||||||
							
								
								
									
										47
									
								
								config.py
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								config.py
									
									
									
									
									
								
							| @ -199,52 +199,6 @@ def build_config(_config_file): | |||||||
|                         'LAST_PING_ACK_TIME': 0, |                         'LAST_PING_ACK_TIME': 0, | ||||||
|                     }}) |                     }}) | ||||||
| 
 | 
 | ||||||
|                 if config.get(section, 'MODE') == 'XLXPEER': |  | ||||||
|                     CONFIG['SYSTEMS'].update({section: { |  | ||||||
|                         'MODE': config.get(section, 'MODE'), |  | ||||||
|                         'ENABLED': config.getboolean(section, 'ENABLED'), |  | ||||||
|                         'LOOSE': config.getboolean(section, 'LOOSE'), |  | ||||||
|                         'SOCK_ADDR': (gethostbyname(config.get(section, 'IP')), config.getint(section, 'PORT')), |  | ||||||
|                         'IP': gethostbyname(config.get(section, 'IP')), |  | ||||||
|                         'PORT': config.getint(section, 'PORT'), |  | ||||||
|                         'MASTER_SOCKADDR': (gethostbyname(config.get(section, 'MASTER_IP')), config.getint(section, 'MASTER_PORT')), |  | ||||||
|                         'MASTER_IP': gethostbyname(config.get(section, 'MASTER_IP')), |  | ||||||
|                         'MASTER_PORT': config.getint(section, 'MASTER_PORT'), |  | ||||||
|                         'PASSPHRASE': bytes(config.get(section, 'PASSPHRASE'), 'utf-8'), |  | ||||||
|                         'CALLSIGN': bytes(config.get(section, 'CALLSIGN').ljust(8)[:8], 'utf-8'), |  | ||||||
|                         'RADIO_ID': config.getint(section, 'RADIO_ID').to_bytes(4, 'big'), |  | ||||||
|                         'RX_FREQ': bytes(config.get(section, 'RX_FREQ').ljust(9)[:9], 'utf-8'), |  | ||||||
|                         'TX_FREQ': bytes(config.get(section, 'TX_FREQ').ljust(9)[:9], 'utf-8'), |  | ||||||
|                         'TX_POWER': bytes(config.get(section, 'TX_POWER').rjust(2,'0'), 'utf-8'), |  | ||||||
|                         'COLORCODE': bytes(config.get(section, 'COLORCODE').rjust(2,'0'), 'utf-8'), |  | ||||||
|                         'LATITUDE': bytes(config.get(section, 'LATITUDE').ljust(8)[:8], 'utf-8'), |  | ||||||
|                         'LONGITUDE': bytes(config.get(section, 'LONGITUDE').ljust(9)[:9], 'utf-8'), |  | ||||||
|                         'HEIGHT': bytes(config.get(section, 'HEIGHT').rjust(3,'0'), 'utf-8'), |  | ||||||
|                         'LOCATION': bytes(config.get(section, 'LOCATION').ljust(20)[:20], 'utf-8'), |  | ||||||
|                         'DESCRIPTION': bytes(config.get(section, 'DESCRIPTION').ljust(19)[:19], 'utf-8'), |  | ||||||
|                         'SLOTS': bytes(config.get(section, 'SLOTS'), 'utf-8'), |  | ||||||
|                         'URL': bytes(config.get(section, 'URL').ljust(124)[:124], 'utf-8'), |  | ||||||
|                         'SOFTWARE_ID': bytes(config.get(section, 'SOFTWARE_ID').ljust(40)[:40], 'utf-8'), |  | ||||||
|                         'PACKAGE_ID': bytes(config.get(section, 'PACKAGE_ID').ljust(40)[:40], 'utf-8'), |  | ||||||
|                         'GROUP_HANGTIME': config.getint(section, 'GROUP_HANGTIME'), |  | ||||||
|                         'XLXMODULE': config.getint(section, 'XLXMODULE'), |  | ||||||
|                         'OPTIONS': '', |  | ||||||
|                         'USE_ACL': config.getboolean(section, 'USE_ACL'), |  | ||||||
|                         'SUB_ACL': config.get(section, 'SUB_ACL'), |  | ||||||
|                         'TG1_ACL': config.get(section, 'TGID_TS1_ACL'), |  | ||||||
|                         'TG2_ACL': config.get(section, 'TGID_TS2_ACL') |  | ||||||
|                     }}) |  | ||||||
|                     CONFIG['SYSTEMS'][section].update({'XLXSTATS': { |  | ||||||
|                         'CONNECTION': 'NO',             # NO, RTPL_SENT, AUTHENTICATED, CONFIG-SENT, YES  |  | ||||||
|                         'CONNECTED': None, |  | ||||||
|                         'PINGS_SENT': 0, |  | ||||||
|                         'PINGS_ACKD': 0, |  | ||||||
|                         'NUM_OUTSTANDING': 0, |  | ||||||
|                         'PING_OUTSTANDING': False, |  | ||||||
|                         'LAST_PING_TX_TIME': 0, |  | ||||||
|                         'LAST_PING_ACK_TIME': 0, |  | ||||||
|                     }}) |  | ||||||
| 
 |  | ||||||
|                 elif config.get(section, 'MODE') == 'MASTER': |                 elif config.get(section, 'MODE') == 'MASTER': | ||||||
|                     CONFIG['SYSTEMS'].update({section: { |                     CONFIG['SYSTEMS'].update({section: { | ||||||
|                         'MODE': config.get(section, 'MODE'), |                         'MODE': config.get(section, 'MODE'), | ||||||
| @ -274,6 +228,7 @@ def build_config(_config_file): | |||||||
|                         'TARGET_SOCK': (gethostbyname(config.get(section, 'TARGET_IP')), config.getint(section, 'TARGET_PORT')), |                         'TARGET_SOCK': (gethostbyname(config.get(section, 'TARGET_IP')), config.getint(section, 'TARGET_PORT')), | ||||||
|                         'TARGET_IP': gethostbyname(config.get(section, 'TARGET_IP')), |                         'TARGET_IP': gethostbyname(config.get(section, 'TARGET_IP')), | ||||||
|                         'TARGET_PORT': config.getint(section, 'TARGET_PORT'), |                         'TARGET_PORT': config.getint(section, 'TARGET_PORT'), | ||||||
|  |                         'BOTH_SLOTS': config.getboolean(section, 'BOTH_SLOTS'), | ||||||
|                         'USE_ACL': config.getboolean(section, 'USE_ACL'), |                         'USE_ACL': config.getboolean(section, 'USE_ACL'), | ||||||
|                         'SUB_ACL': config.get(section, 'SUB_ACL'), |                         'SUB_ACL': config.get(section, 'SUB_ACL'), | ||||||
|                         'TG1_ACL': config.get(section, 'TGID_ACL'), |                         'TG1_ACL': config.get(section, 'TGID_ACL'), | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								entrypoint
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								entrypoint
									
									
									
									
									
								
							| @ -1,19 +0,0 @@ | |||||||
| #!/bin/sh |  | ||||||
| 
 |  | ||||||
| if [ -z "$GIT_REPO" ]; then |  | ||||||
|   mkdir -p /var/tmp/config  |  | ||||||
|   cd /var/tmp/config |  | ||||||
|   git clone https://${GIT_USER}:${GIT_PASSWORD}@${GIT_REPO} |  | ||||||
| 
 |  | ||||||
|   DIR=$(echo ${GIT_REPO}| sed s/.git$//g | sed s#^.*/##g) |  | ||||||
| 
 |  | ||||||
|   cp -a /var/tmp/config/${DIR}/*cfg /opt/hblink3/ |  | ||||||
|   cp -a /var/tmp/config/${DIR}/*csv /opt/hblink3/ |  | ||||||
|   cp -a /var/tmp/config/${DIR}/*json /opt/hblink3/ |  | ||||||
| else |  | ||||||
|   cp -a /opt/config/*cfg /opt/hblink3/ |  | ||||||
|   cp -a /opt/config/*csv /opt/hblink3/ |  | ||||||
|   cp -a /opt/config/*json /opt/hblink3/ |  | ||||||
| fi |  | ||||||
| cd /opt/hblink3 |  | ||||||
| python /opt/hblink3/hblink.py -c hblink.cfg |  | ||||||
							
								
								
									
										127
									
								
								hblink-750.cfg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										127
									
								
								hblink-750.cfg
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | [GLOBAL] | ||||||
|  | PATH: ./ | ||||||
|  | PING_TIME: 5 | ||||||
|  | MAX_MISSED: 3 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: PERMIT:ALL | ||||||
|  | TGID_TS2_ACL: PERMIT:ALL | ||||||
|  | 
 | ||||||
|  | [REPORTS] | ||||||
|  | REPORT: False | ||||||
|  | REPORT_INTERVAL: 60 | ||||||
|  | REPORT_PORT: 4321 | ||||||
|  | REPORT_CLIENTS: 127.0.0.1 | ||||||
|  | 
 | ||||||
|  | [LOGGER] | ||||||
|  | LOG_FILE: /tmp/hblink.log | ||||||
|  | LOG_HANDLERS: console-timed | ||||||
|  | LOG_LEVEL: INFO | ||||||
|  | LOG_NAME: 444.750 | ||||||
|  | 
 | ||||||
|  | [ALIASES] | ||||||
|  | TRY_DOWNLOAD: False | ||||||
|  | PATH: ./ | ||||||
|  | PEER_FILE: peer_ids.json | ||||||
|  | SUBSCRIBER_FILE: subscriber_ids.json | ||||||
|  | TGID_FILE: talkgroup_ids.json | ||||||
|  | PEER_URL: https://www.radioid.net/static/rptrs.json | ||||||
|  | SUBSCRIBER_URL: https://www.radioid.net/static/users.json | ||||||
|  | STALE_DAYS: 7 | ||||||
|  | 
 | ||||||
|  | [OBP] | ||||||
|  | MODE: OPENBRIDGE | ||||||
|  | ENABLED: True | ||||||
|  | IP: | ||||||
|  | PORT: 50100 | ||||||
|  | NETWORK_ID: 1 | ||||||
|  | PASSPHRASE: deadbeef | ||||||
|  | #TARGET_IP: olympic.k0usy.org | ||||||
|  | TARGET_IP: 127.0.0.1 | ||||||
|  | #TARGET_PORT: 50666 | ||||||
|  | TARGET_PORT: 50101 | ||||||
|  | BOTH_SLOTS: True | ||||||
|  | USE_ACL: False | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_ACL: PERMIT:ALL | ||||||
|  | 
 | ||||||
|  | [444.750] | ||||||
|  | MODE: MASTER | ||||||
|  | ENABLED: True | ||||||
|  | REPEAT: True | ||||||
|  | MAX_PEERS: 5 | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP: | ||||||
|  | PORT: 50001 | ||||||
|  | PASSPHRASE: jimmy | ||||||
|  | GROUP_HANGTIME: 10 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: DENY:8 | ||||||
|  | TGID_TS2_ACL: PERMIT:3120 | ||||||
|  | 
 | ||||||
|  | [TWO] | ||||||
|  | MODE: MASTER | ||||||
|  | ENABLED: False | ||||||
|  | REPEAT: True | ||||||
|  | MAX_PEERS: 5 | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP: | ||||||
|  | PORT:50002 | ||||||
|  | PASSPHRASE: jimmy | ||||||
|  | GROUP_HANGTIME: 10 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: DENY:8 | ||||||
|  | TGID_TS2_ACL: PERMIT:3120 | ||||||
|  | 
 | ||||||
|  | [THREE] | ||||||
|  | MODE: MASTER | ||||||
|  | ENABLED: False | ||||||
|  | REPEAT: True | ||||||
|  | MAX_PEERS: 5 | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP: | ||||||
|  | PORT:50003 | ||||||
|  | PASSPHRASE: jimmy | ||||||
|  | GROUP_HANGTIME: 10 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: DENY:8 | ||||||
|  | TGID_TS2_ACL: PERMIT:3120 | ||||||
|  | 
 | ||||||
|  | [KS-DMR] | ||||||
|  | MODE: PEER | ||||||
|  | ENABLED: False | ||||||
|  | LOOSE: False | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP:  | ||||||
|  | PORT: 54001 | ||||||
|  | MASTER_IP: olympic.k0usy.org | ||||||
|  | MASTER_PORT: 62071 | ||||||
|  | PASSPHRASE: c0ffee | ||||||
|  | CALLSIGN: W1ABC | ||||||
|  | RADIO_ID: 312312 | ||||||
|  | RX_FREQ: 449000000 | ||||||
|  | TX_FREQ: 444000000 | ||||||
|  | TX_POWER: 25 | ||||||
|  | COLORCODE: 1 | ||||||
|  | SLOTS: 1 | ||||||
|  | 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 | ||||||
|  | OPTIONS: | ||||||
|  | USE_ACL: True | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: PERMIT:ALL | ||||||
|  | TGID_TS2_ACL: PERMIT:ALL | ||||||
							
								
								
									
										127
									
								
								hblink-800.cfg
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										127
									
								
								hblink-800.cfg
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,127 @@ | |||||||
|  | [GLOBAL] | ||||||
|  | PATH: ./ | ||||||
|  | PING_TIME: 5 | ||||||
|  | MAX_MISSED: 3 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: PERMIT:ALL | ||||||
|  | TGID_TS2_ACL: PERMIT:ALL | ||||||
|  | 
 | ||||||
|  | [REPORTS] | ||||||
|  | REPORT: False | ||||||
|  | REPORT_INTERVAL: 60 | ||||||
|  | REPORT_PORT: 4321 | ||||||
|  | REPORT_CLIENTS: 127.0.0.1 | ||||||
|  | 
 | ||||||
|  | [LOGGER] | ||||||
|  | LOG_FILE: /tmp/hblink.log | ||||||
|  | LOG_HANDLERS: console-timed | ||||||
|  | LOG_LEVEL: INFO | ||||||
|  | LOG_NAME: 444.800 | ||||||
|  | 
 | ||||||
|  | [ALIASES] | ||||||
|  | TRY_DOWNLOAD: False | ||||||
|  | PATH: ./ | ||||||
|  | PEER_FILE: peer_ids.json | ||||||
|  | SUBSCRIBER_FILE: subscriber_ids.json | ||||||
|  | TGID_FILE: talkgroup_ids.json | ||||||
|  | PEER_URL: https://www.radioid.net/static/rptrs.json | ||||||
|  | SUBSCRIBER_URL: https://www.radioid.net/static/users.json | ||||||
|  | STALE_DAYS: 7 | ||||||
|  | 
 | ||||||
|  | [OBP] | ||||||
|  | MODE: OPENBRIDGE | ||||||
|  | ENABLED: True | ||||||
|  | IP: | ||||||
|  | PORT: 50101 | ||||||
|  | NETWORK_ID: 2 | ||||||
|  | PASSPHRASE: deadbeef | ||||||
|  | #TARGET_IP: olympic.k0usy.org | ||||||
|  | TARGET_IP: 127.0.0.1 | ||||||
|  | #TARGET_PORT: 50666 | ||||||
|  | TARGET_PORT: 50100 | ||||||
|  | BOTH_SLOTS: True | ||||||
|  | USE_ACL: False | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_ACL: PERMIT:ALL | ||||||
|  | 
 | ||||||
|  | [444.800] | ||||||
|  | MODE: MASTER | ||||||
|  | ENABLED: True | ||||||
|  | REPEAT: True | ||||||
|  | MAX_PEERS: 5 | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP: | ||||||
|  | PORT: 50011 | ||||||
|  | PASSPHRASE: jimmy | ||||||
|  | GROUP_HANGTIME: 10 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: DENY:8 | ||||||
|  | TGID_TS2_ACL: PERMIT:3120 | ||||||
|  | 
 | ||||||
|  | [TWO] | ||||||
|  | MODE: MASTER | ||||||
|  | ENABLED: False | ||||||
|  | REPEAT: True | ||||||
|  | MAX_PEERS: 5 | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP: | ||||||
|  | PORT:50012 | ||||||
|  | PASSPHRASE: jimmy | ||||||
|  | GROUP_HANGTIME: 10 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: DENY:8 | ||||||
|  | TGID_TS2_ACL: PERMIT:3120 | ||||||
|  | 
 | ||||||
|  | [THREE] | ||||||
|  | MODE: MASTER | ||||||
|  | ENABLED: False | ||||||
|  | REPEAT: True | ||||||
|  | MAX_PEERS: 5 | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP: | ||||||
|  | PORT:50013 | ||||||
|  | PASSPHRASE: jimmy | ||||||
|  | GROUP_HANGTIME: 10 | ||||||
|  | USE_ACL: False | ||||||
|  | REG_ACL: DENY:1 | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: DENY:8 | ||||||
|  | TGID_TS2_ACL: PERMIT:3120 | ||||||
|  | 
 | ||||||
|  | [KS-DMR] | ||||||
|  | MODE: PEER | ||||||
|  | ENABLED: False | ||||||
|  | LOOSE: False | ||||||
|  | EXPORT_AMBE: False | ||||||
|  | IP:  | ||||||
|  | PORT: 54011 | ||||||
|  | MASTER_IP: olympic.k0usy.org | ||||||
|  | MASTER_PORT: 62071 | ||||||
|  | PASSPHRASE: c0ffee | ||||||
|  | CALLSIGN: W1ABC | ||||||
|  | RADIO_ID: 312312 | ||||||
|  | RX_FREQ: 449000000 | ||||||
|  | TX_FREQ: 444000000 | ||||||
|  | TX_POWER: 25 | ||||||
|  | COLORCODE: 1 | ||||||
|  | SLOTS: 1 | ||||||
|  | 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 | ||||||
|  | OPTIONS: | ||||||
|  | USE_ACL: True | ||||||
|  | SUB_ACL: DENY:1 | ||||||
|  | TGID_TS1_ACL: PERMIT:ALL | ||||||
|  | TGID_TS2_ACL: PERMIT:ALL | ||||||
| @ -120,7 +120,9 @@ STALE_DAYS: 7 | |||||||
| # | # | ||||||
| # ACLs: | # ACLs: | ||||||
| # OpenBridge does not 'register', so registration ACL is meaningless. | # OpenBridge does not 'register', so registration ACL is meaningless. | ||||||
| # OpenBridge passes all traffic on TS1, so there is only 1 TGID ACL. | # Proper OpenBridge passes all traffic on TS1. | ||||||
|  | # HBlink can extend OPB to use both slots for unit calls only. | ||||||
|  | # Setting "BOTH_SLOTS" True ONLY affects unit traffic! | ||||||
| # Otherwise ACLs work as described in the global stanza | # Otherwise ACLs work as described in the global stanza | ||||||
| [OBP-1] | [OBP-1] | ||||||
| MODE: OPENBRIDGE | MODE: OPENBRIDGE | ||||||
| @ -131,6 +133,7 @@ NETWORK_ID: 3129100 | |||||||
| PASSPHRASE: password | PASSPHRASE: password | ||||||
| TARGET_IP: 1.2.3.4 | TARGET_IP: 1.2.3.4 | ||||||
| TARGET_PORT: 62035 | TARGET_PORT: 62035 | ||||||
|  | BOTH_SLOTS: True | ||||||
| USE_ACL: True | USE_ACL: True | ||||||
| SUB_ACL: DENY:1 | SUB_ACL: DENY:1 | ||||||
| TGID_ACL: PERMIT:ALL | TGID_ACL: PERMIT:ALL | ||||||
| @ -207,35 +210,3 @@ USE_ACL: True | |||||||
| 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 | ||||||
| 
 |  | ||||||
| [XLX-1] |  | ||||||
| MODE: XLXPEER |  | ||||||
| ENABLED: True |  | ||||||
| LOOSE: True |  | ||||||
| EXPORT_AMBE: False |  | ||||||
| IP:  |  | ||||||
| PORT: 54002 |  | ||||||
| MASTER_IP: 172.16.1.1 |  | ||||||
| MASTER_PORT: 62030 |  | ||||||
| PASSPHRASE: passw0rd |  | ||||||
| CALLSIGN: W1ABC |  | ||||||
| RADIO_ID: 312000 |  | ||||||
| RX_FREQ: 449000000 |  | ||||||
| TX_FREQ: 444000000 |  | ||||||
| TX_POWER: 25 |  | ||||||
| COLORCODE: 1 |  | ||||||
| SLOTS: 1 |  | ||||||
| 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 |  | ||||||
|  | |||||||
							
								
								
									
										42
									
								
								hblink.py
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								hblink.py
									
									
									
									
									
								
							| @ -160,8 +160,8 @@ class OPENBRIDGE(DatagramProtocol): | |||||||
|                 _stream_id = _data[16:20] |                 _stream_id = _data[16:20] | ||||||
|                 #logger.debug('(%s) DMRD - Seqence: %s, RF Source: %s, Destination ID: %s', self._system, int_id(_seq), int_id(_rf_src), int_id(_dst_id)) |                 #logger.debug('(%s) DMRD - Seqence: %s, RF Source: %s, Destination ID: %s', self._system, int_id(_seq), int_id(_rf_src), int_id(_dst_id)) | ||||||
| 
 | 
 | ||||||
|                 # Sanity check for OpenBridge -- all calls must be on Slot 1 |                 # Sanity check for OpenBridge -- all calls must be on Slot 1 for Brandmeister or DMR+. Other HBlinks can process timeslot on OPB if the flag is set | ||||||
|                 if _slot != 1: |                 if _slot != 1 and not self._config['BOTH_SLOTS'] and not _call_type == 'unit': | ||||||
|                     logger.error('(%s) OpenBridge packet discarded because it was not received on slot 1. SID: %s, TGID %s', self._system, int_id(_rf_src), int_id(_dst_id)) |                     logger.error('(%s) OpenBridge packet discarded because it was not received on slot 1. SID: %s, TGID %s', self._system, int_id(_rf_src), int_id(_dst_id)) | ||||||
|                     return |                     return | ||||||
| 
 | 
 | ||||||
| @ -223,13 +223,6 @@ class HBSYSTEM(DatagramProtocol): | |||||||
|             self.datagramReceived = self.peer_datagramReceived |             self.datagramReceived = self.peer_datagramReceived | ||||||
|             self.dereg = self.peer_dereg |             self.dereg = self.peer_dereg | ||||||
| 
 | 
 | ||||||
|         elif self._config['MODE'] == 'XLXPEER': |  | ||||||
|             self._stats = self._config['XLXSTATS'] |  | ||||||
|             self.send_system = self.send_master |  | ||||||
|             self.maintenance_loop = self.peer_maintenance_loop |  | ||||||
|             self.datagramReceived = self.peer_datagramReceived |  | ||||||
|             self.dereg = self.peer_dereg |  | ||||||
| 
 |  | ||||||
|     def startProtocol(self): |     def startProtocol(self): | ||||||
|         # Set up periodic loop for tracking pings from peers. Run every 'PING_TIME' seconds |         # Set up periodic loop for tracking pings from peers. Run every 'PING_TIME' seconds | ||||||
|         self._system_maintenance = task.LoopingCall(self.maintenance_loop) |         self._system_maintenance = task.LoopingCall(self.maintenance_loop) | ||||||
| @ -289,29 +282,6 @@ class HBSYSTEM(DatagramProtocol): | |||||||
|         # KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!! |         # 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)) |         # logger.debug('(%s) TX Packet to %s:%s -- %s', self._system, self._config['MASTER_IP'], self._config['MASTER_PORT'], ahex(_packet)) | ||||||
| 
 | 
 | ||||||
|     def send_xlxmaster(self, radio, xlx, mastersock): |  | ||||||
|         radio3 = int.from_bytes(radio, 'big').to_bytes(3, 'big') |  | ||||||
|         radio4 = int.from_bytes(radio, 'big').to_bytes(4, 'big') |  | ||||||
|         xlx3   = xlx.to_bytes(3, 'big') |  | ||||||
|         streamid = randint(0,255).to_bytes(1, 'big')+randint(0,255).to_bytes(1, 'big')+randint(0,255).to_bytes(1, 'big')+randint(0,255).to_bytes(1, 'big') |  | ||||||
|         # Wait for .5 secs for the XLX to log us in |  | ||||||
|         for packetnr in range(5): |  | ||||||
|             if packetnr < 3: |  | ||||||
|                 # First 3 packets, voice start, stream type e1 |  | ||||||
|                 strmtype = 225 |  | ||||||
|                 payload = bytearray.fromhex('4f2e00b501ae3a001c40a0c1cc7dff57d75df5d5065026f82880bd616f13f185890000') |  | ||||||
|             else: |  | ||||||
|                 # Last 2 packets, voice end, stream type e2 |  | ||||||
|                 strmtype = 226 |  | ||||||
|                 payload = bytearray.fromhex('4f410061011e3a781c30a061ccbdff57d75df5d2534425c02fe0b1216713e885ba0000') |  | ||||||
|             packetnr1 = packetnr.to_bytes(1, 'big') |  | ||||||
|             strmtype1 = strmtype.to_bytes(1, 'big') |  | ||||||
|             _packet = b''.join([DMRD, packetnr1, radio3, xlx3, radio4, strmtype1, streamid, payload]) |  | ||||||
|             self.transport.write(_packet, mastersock) |  | ||||||
|             # KEEP THE FOLLOWING COMMENTED OUT UNLESS YOU'RE DEBUGGING DEEPLY!!!! |  | ||||||
|             #logger.debug('(%s) XLX Module Change Packet: %s', self._system, ahex(_packet)) |  | ||||||
|         return |  | ||||||
| 
 |  | ||||||
|     def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): |     def dmrd_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _call_type, _frame_type, _dtype_vseq, _stream_id, _data): | ||||||
|         pass |         pass | ||||||
| 
 | 
 | ||||||
| @ -656,11 +626,7 @@ class HBSYSTEM(DatagramProtocol): | |||||||
|                             self._stats['CONNECTION'] = 'YES' |                             self._stats['CONNECTION'] = 'YES' | ||||||
|                             self._stats['CONNECTED'] = time() |                             self._stats['CONNECTED'] = time() | ||||||
|                             logger.info('(%s) Connection to Master Completed', self._system) |                             logger.info('(%s) Connection to Master Completed', self._system) | ||||||
|                             # If we are an XLX, send the XLX module request here. |                              | ||||||
|                             if self._config['MODE'] == 'XLXPEER': |  | ||||||
|                                 self.send_xlxmaster(self._config['RADIO_ID'], int(4000), self._config['MASTER_SOCKADDR']) |  | ||||||
|                                 self.send_xlxmaster(self._config['RADIO_ID'], self._config['XLXMODULE'], self._config['MASTER_SOCKADDR']) |  | ||||||
|                                 logger.info('(%s) Sending XLX Module request', self._system) |  | ||||||
|                     else: |                     else: | ||||||
|                         self._stats['CONNECTION'] = 'NO' |                         self._stats['CONNECTION'] = 'NO' | ||||||
|                         logger.error('(%s) Master ACK Contained wrong ID - Connection Reset', self._system) |                         logger.error('(%s) Master ACK Contained wrong ID - Connection Reset', self._system) | ||||||
| @ -797,7 +763,7 @@ 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('\n\nCopyright (c) 2013, 2014, 2015, 2016, 2018, 2019, 2020\n\tThe Regents of the K0USY Group. All rights reserved.\n') | ||||||
|     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 | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								rules-750.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								rules-750.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | BRIDGES = { | ||||||
|  |     '1/2': [ | ||||||
|  |             {'SYSTEM': '444.750',    'TS': 1, 'TGID': 2,    'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []}, | ||||||
|  |             {'SYSTEM': 'OBP',        'TS': 1, 'TGID': 2,    'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []} | ||||||
|  |         ], | ||||||
|  |     'KANSAS': [ | ||||||
|  |             {'SYSTEM': '444.750',    'TS': 2, 'TGID': 3120, 'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []}, | ||||||
|  |             {'SYSTEM': 'OBP',        'TS': 1, 'TGID': 3120, 'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []} | ||||||
|  |         ] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | UNIT = ['444.750', 'OBP'] | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     from pprint import pprint | ||||||
|  |     pprint(BRIDGES) | ||||||
							
								
								
									
										16
									
								
								rules-800.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										16
									
								
								rules-800.py
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | BRIDGES = { | ||||||
|  |     '1/2': [ | ||||||
|  |             {'SYSTEM': '444.800',    'TS': 1, 'TGID': 2,    'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []}, | ||||||
|  |             {'SYSTEM': 'OBP',        'TS': 1, 'TGID': 2,    'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []} | ||||||
|  |         ], | ||||||
|  |     'KANSAS': [ | ||||||
|  |             {'SYSTEM': '444.800',    'TS': 2, 'TGID': 3120, 'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []}, | ||||||
|  |             {'SYSTEM': 'OBP',        'TS': 1, 'TGID': 3120, 'ACTIVE': True, 'TIMEOUT': 5,'TO_TYPE': 'NONE',   'ON': [], 'OFF': [], 'RESET': []} | ||||||
|  |         ] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | UNIT = ["444.800", "OBP"] | ||||||
|  | 
 | ||||||
|  | if __name__ == '__main__': | ||||||
|  |     from pprint import pprint | ||||||
|  |     pprint(BRIDGES) | ||||||
| @ -47,6 +47,18 @@ BRIDGES = { | |||||||
|         ] |         ] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ''' | ||||||
|  | list the names of each system that should bridge unit to unit (individual) calls. | ||||||
|  | ''' | ||||||
|  | 
 | ||||||
|  | UNIT = ['ONE', 'TWO'] | ||||||
|  | 
 | ||||||
|  | ''' | ||||||
|  | This is for testing the syntax of the file. It won't eliminate all errors, but running this file | ||||||
|  | like it were a Python program itself will tell you if the syntax is correct! | ||||||
|  | ''' | ||||||
|  | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     from pprint import pprint |     from pprint import pprint | ||||||
|     pprint(BRIDGES) |     pprint(BRIDGES) | ||||||
|  |     print(UNIT) | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								voice_lib.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								voice_lib.py
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user