AMBE Export options added

This commit is contained in:
Cort Buffington 2016-07-30 20:37:05 -05:00
parent 0659ccb424
commit dd77705701
4 changed files with 98 additions and 12 deletions

50
hb_bridge.py Executable file
View File

@ -0,0 +1,50 @@
#!/usr/bin/env python
#
# This work is licensed under the Creative Attribution-NonCommercial-ShareAlike
# 3.0 Unported License.To view a copy of this license, visit
# http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to
# Creative Commons, 444 Castro Street, Suite 900, Mountain View,
# California, 94041, USA.
from __future__ import print_function
# Twisted is pretty important, so I keep it separate
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor
from twisted.internet import task
# Things we import from the main hblink module
from hblink import CONFIG, HBMASTER, HBCLIENT, logger
# 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 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__ = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported'
__maintainer__ = 'Cort Buffington, N0MJS'
__email__ = 'n0mjs@me.com'
__status__ = 'pre-alpha'
#************************************************
# MAIN PROGRAM LOOP STARTS HERE
#************************************************
if __name__ == '__main__':
logger.info('HBlink \'HBlink.py\' (c) 2016 N0MJS & the K0USY Group - SYSTEM STARTING...')
# HBlink Master
masters = {}
for master in CONFIG['MASTERS']:
if CONFIG['MASTERS'][master]['ENABLED']:
masters[master] = HBMASTER(master)
reactor.listenUDP(CONFIG['MASTERS'][master]['PORT'], masters[master], interface=CONFIG['MASTERS'][master]['IP'])
logger.debug('MASTER instance created: %s, %s', master, masters[master])
clients = {}
for client in CONFIG['CLIENTS']:
if CONFIG['CLIENTS'][client]['ENABLED']:
clients[client] = HBCLIENT(client)
reactor.listenUDP(CONFIG['CLIENTS'][client]['PORT'], clients[client], interface=CONFIG['CLIENTS'][client]['IP'])
logger.debug('CLIENT instance created: %s, %s', client, clients[client])
reactor.run()

View File

@ -14,6 +14,7 @@ def build_config(_config_file):
CONFIG = {}
CONFIG['GLOBAL'] = {}
CONFIG['LOGGER'] = {}
CONFIG['AMBE'] = {}
CONFIG['CLIENTS'] = {}
CONFIG['MASTERS'] = {}
@ -36,12 +37,20 @@ def build_config(_config_file):
'LOG_LEVEL': config.get(section, 'LOG_LEVEL'),
'LOG_NAME': config.get(section, 'LOG_NAME')
})
elif section == 'AMBE':
# Process AMBE Export items in the configuration
CONFIG['AMBE'].update({
'EXPORT_IP': gethostbyname(config.get(section, 'EXPORT_IP')),
'EXPORT_PORT': config.getint(section, 'EXPORT_PORT'),
})
elif config.getboolean(section, 'ENABLED'):
# HomeBrew Client (Repeater) Configuration(s)
if config.get(section, 'MODE') == 'CLIENT':
CONFIG['CLIENTS'].update({section: {
'ENABLED': config.getboolean(section, 'ENABLED'),
'EXPORT_AMBE': config.getboolean(section, 'EXPORT_AMBE'),
'IP': gethostbyname(config.get(section, 'IP')),
'PORT': config.getint(section, 'PORT'),
'MASTER_IP': gethostbyname(config.get(section, 'MASTER_IP')),
@ -77,6 +86,7 @@ def build_config(_config_file):
CONFIG['MASTERS'].update({section: {
'ENABLED': config.getboolean(section, 'ENABLED'),
'REPEAT': config.getboolean(section, 'REPEAT'),
'EXPORT_AMBE': config.getboolean(section, 'EXPORT_AMBE'),
'IP': gethostbyname(config.get(section, 'IP')),
'PORT': config.getint(section, 'PORT'),
'PASSPHRASE': config.get(section, 'PASSPHRASE')
@ -88,6 +98,4 @@ def build_config(_config_file):
print "Cannot parse configuration file. %s" %err
sys.exit('Could not parse configuration file, exiting...')
return CONFIG
return CONFIG

View File

@ -19,6 +19,13 @@ LOG_HANDLERS: console-timed
LOG_LEVEL: DEBUG
LOG_NAME: HBlink
# EXPORT AMBE DATA
# This is for exporting AMBE audio frames to an an "external" process for
# decoding or other nefarious actions.
[AMBE]
EXPORT_IP: 127.0.0.1
EXPORT_PORT: 1234
# MASTER INSTANCES - DUPLICATE SECTION FOR MULTIPLE MASTERS
# HomeBrew Protocol Master instances go here.
# IP may be left blank if there's one interface on your system.
@ -29,6 +36,7 @@ LOG_NAME: HBlink
MODE: MASTER
ENABLED: True
REPEAT: True
EXPORT_AMBE: False
IP:
PORT: 54000
PASSPHRASE: s3cr37w0rd
@ -43,6 +51,7 @@ PASSPHRASE: s3cr37w0rd
[REPEATER-1]
MODE: CLIENT
ENABLED: True
EXPORT_AMBE: False
IP:
PORT: 54001
MASTER_IP: 172.16.1.1

View File

@ -38,7 +38,7 @@ import hb_config
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
__author__ = 'Cortney T. Buffington, N0MJS'
__copyright__ = 'Copyright (c) 2013 - 2016 Cortney T. Buffington, N0MJS and the K0USY Group'
__copyright__ = 'Copyright (c) 2016 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__ = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported'
__maintainer__ = 'Cort Buffington, N0MJS'
@ -116,6 +116,9 @@ def int_id(_hex_string):
class AMBE:
_sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
_exp_ip = CONFIG['AMBE']['EXPORT_IP']
_exp_port = CONFIG['AMBE']['EXPORT_PORT']
def parseAMBE(self, _client, _data):
_seq = int_id(_data[4:5])
_srcID = int_id(_data[5:8])
@ -136,9 +139,9 @@ class AMBE:
#_sock.sendto(_ambe.tobytes(), ("127.0.0.1", 31000))
ambeBytes = _ambe.tobytes()
self._sock.sendto(ambeBytes[0:9], ("127.0.0.1", 31000))
self._sock.sendto(ambeBytes[9:18], ("127.0.0.1", 31000))
self._sock.sendto(ambeBytes[18:27], ("127.0.0.1", 31000))
self._sock.sendto(ambeBytes[0:9], (self._exp_ip, self._exp_port))
self._sock.sendto(ambeBytes[9:18], (self._exp_ip, self._exp_port))
self._sock.sendto(ambeBytes[18:27], (self._exp_ip, self._exp_port))
#************************************************
# HB MASTER CLASS
@ -151,6 +154,10 @@ class HBMASTER(DatagramProtocol):
self._master = args[0]
self._config = CONFIG['MASTERS'][self._master]
self._clients = CONFIG['MASTERS'][self._master]['CLIENTS']
# Configure for AMBE audio export if enabled
if self._config['EXPORT_AMBE']:
self._ambe = AMBE()
else:
# If we didn't get called correctly, log it and quit.
logger.error('(%s) HBMASTER was not called with an argument. Terminating', self._master)
@ -183,6 +190,11 @@ class HBMASTER(DatagramProtocol):
_rf_src = _data[5:8]
_dst_id = _data[8:11]
logger.debug('(%s) DMRD - Seqence: %s, RF Source: %s, Destination ID: %s', self._master, int_id(_seq), int_id(_rf_src), int_id(_dst_id))
# If AMBE audio exporting is configured...
if self._config['EXPORT_AMBE']:
self._ambe.parseAMBE(self._master, _data)
if self._config['REPEAT'] == True:
for _client in self._clients:
if _client != _radio_id:
@ -319,19 +331,23 @@ class HBMASTER(DatagramProtocol):
#************************************************
# HB CLIENT CLASS
#************************************************
class HBCLIENT(DatagramProtocol):
ambe = AMBE()
def __init__(self, *args, **kwargs):
if len(args) == 1:
self._client = args[0]
self._config = CONFIG['CLIENTS'][self._client]
self._stats = self._config['STATS']
# Configure for AMBE audio export if enabled
if self._config['EXPORT_AMBE']:
self._ambe = AMBE()
else:
# If we didn't get called correctly, log it!
logger.error('(%s) HBCLIENT was not called with an argument. Terminating', self._client)
sys.exit()
def startProtocol(self):
# Set up periodic loop for sending pings to the master. Run every 'PING_TIME' seconds
self._client_maintenance = task.LoopingCall(self.client_maintenance_loop)
@ -362,7 +378,10 @@ class HBCLIENT(DatagramProtocol):
_rf_src = _data[5:8]
_dst_id = _data[8:11]
logger.debug('(%s) DMRD - Seqence: %s, RF Source: %s, Destination ID: %s', self._client, h(_seq), int_id(_rf_src), int_id(_dst_id))
self.ambe.parseAMBE(self._client, _data)
# If AMBE audio exporting is configured...
if self._config['EXPORT_AMBE']:
self._ambe.parseAMBE(self._client, _data)
def datagramReceived(self, _data, (_host, _port)):
# Validate that we receveived this packet from the master - security check!
@ -465,4 +484,4 @@ if __name__ == '__main__':
reactor.listenUDP(CONFIG['CLIENTS'][client]['PORT'], clients[client], interface=CONFIG['CLIENTS'][client]['IP'])
logger.debug('CLIENT instance created: %s, %s', client, clients[client])
reactor.run()
reactor.run()