AMBE Export options added
This commit is contained in:
parent
0659ccb424
commit
dd77705701
|
@ -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()
|
14
hb_config.py
14
hb_config.py
|
@ -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
|
|
@ -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
|
||||
|
|
37
hblink.py
37
hblink.py
|
@ -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()
|
Loading…
Reference in New Issue