diff --git a/ambe_audio.py b/ambe_audio.py index 82c3d9f..54d6ce9 100755 --- a/ambe_audio.py +++ b/ambe_audio.py @@ -14,11 +14,9 @@ from twisted.internet import reactor from binascii import b2a_hex as h from bitstring import BitArray -import sys +import sys, socket, ConfigParser, thread, traceback import cPickle as pickle from dmrlink import IPSC, NETWORK, networks, logger, int_id, hex_str_3, get_info, talkgroup_ids, subscriber_ids -import socket -import ConfigParser __author__ = 'Cortney T. Buffington, N0MJS' __copyright__ = 'Copyright (c) 2015 Cortney T. Buffington, N0MJS and the K0USY Group' @@ -34,65 +32,84 @@ try: except ImportError: sys.exit('IPSC message types file not found or invalid') -# Utility function to convert bytes to string of hex values (for debug) -def ByteToHex( byteStr ): - return ''.join( [ "%02X " % ord(x) for x in byteStr ] ).strip() # -# Define default values for operation. These will be overridden by the .cfg file if found +# ambeIPSC class, # -_configFile='ambe_audio.cfg' -_debug = False -_outToFile = False -_outToUDP = True -#_gateway = "192.168.1.184" -_gateway = "127.0.0.1" -_gateway_port = 1234 -_remote_control_port = 1235 -_tg_filter = [2,3,13,3174,3777215,3100,9,9998,3112] #set this to the tg to monitor -_no_tg = -99 - - -# -# Now read the configuration file and parse out the values we need -# -config = ConfigParser.ConfigParser() -try: - _tg_filter=[] - config.read(_configFile) - for sec in config.sections(): - for key, val in config.items(sec): - print( '%s="%s"' % (key, val) ) - _debug = config.get(sec, '_debug') - _outToFile = config.get(sec, '_outToFile') - _outToUDP = config.get(sec, '_outToUDP') - _gateway = config.get(sec, '_gateway') - _gateway_port = config.get(sec, '_gateway_port') - _tgs = config.get(sec, '_tg_filter') - _tg_filter = map(int, _tgs.split(',')) - -except: - sys.exit('Configuration file \''+_configFile+'\' is not a valid configuration file! Exiting...') - - -# -# Open output sincs, should be inside of the class.... -# -if _outToFile == True: - f = open('ambe.bin', 'wb') -if _outToUDP == True: - sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) - class ambeIPSC(IPSC): - _currentTG = _no_tg - + + _configFile='ambe_audio.cfg' + _debug = False + _outToFile = False + _outToUDP = True + #_gateway = "192.168.1.184" + _gateway = "127.0.0.1" + _gateway_port = 1234 + _remote_control_port = 1235 + _tg_filter = [2,3,13,3174,3777215,3100,9,9998,3112] #set this to the tg to monitor + _no_tg = -99 + _sock = -1; + def __init__(self, *args, **kwargs): IPSC.__init__(self, *args, **kwargs) self.CALL_DATA = [] - self._currentTG = _no_tg - print('DMRLink ambe server') - print('Send UDP frames to gateway {}:{}'.format(_gateway, _gateway_port)) + + + # + # Define default values for operation. These will be overridden by the .cfg file if found + # + + self._currentTG = self._no_tg + self._sequenceNr = 0 + self.readConfigFile(self._configFile) + print('DMRLink ambe server') + + # + # Open output sincs + # + if self._outToFile == True: + f = open('ambe.bin', 'wb') + print('Opening output file: ambe.bin') + if self._outToUDP == True: + self._sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) + print('Send UDP frames to DMR gateway {}:{}'.format(self._gateway, self._gateway_port)) + + try: + thread.start_new_thread( self.remote_control, (self._remote_control_port, ) ) + except: + traceback.print_exc() + print( "Error: unable to start thread" ) + + + # Utility function to convert bytes to string of hex values (for debug) + def ByteToHex( byteStr ): + return ''.join( [ "%02X " % ord(x) for x in byteStr ] ).strip() + + # + # Now read the configuration file and parse out the values we need + # + def readConfigFile(self, configFileName): + config = ConfigParser.ConfigParser() + try: + self._tg_filter=[] + config.read(configFileName) + for sec in config.sections(): + for key, val in config.items(sec): + if self._debug == True: + print( '%s="%s"' % (key, val) ) + self._debug = (config.get(sec, '_debug') == "True") + self._outToFile = (config.get(sec, '_outToFile') == "True") + self._outToUDP = (config.get(sec, '_outToUDP') == "True") + self._gateway = config.get(sec, '_gateway') + self._gateway_port = int(config.get(sec, '_gateway_port')) + _tgs = config.get(sec, '_tg_filter') + self._tg_filter = map(int, _tgs.split(',')) + + except: + traceback.print_exc() + sys.exit('Configuration file \''+configFileName+'\' is not a valid configuration file! Exiting...') + #************************************************ # CALLBACK FUNCTIONS FOR USER PACKET TYPES #************************************************ @@ -108,10 +125,10 @@ class ambeIPSC(IPSC): _ambe_frame3 = _ambe_frames[100:149] _tg_id = int_id(_dst_sub) - if _tg_id in _tg_filter: #All TGs + if _tg_id in self._tg_filter: #All TGs _dst_sub = get_info(int_id(_dst_sub), talkgroup_ids) if _payload_type == BURST_DATA_TYPE['VOICE_HEAD']: - if self._currentTG == _no_tg: + if self._currentTG == self._no_tg: if _ts: _ts = 2 else: _ts = 1 _src_sub = get_info(int_id(_src_sub), subscriber_ids) @@ -123,77 +140,58 @@ class ambeIPSC(IPSC): if _payload_type == BURST_DATA_TYPE['VOICE_TERM']: if self._currentTG == _tg_id: print('Voice Transmission End') - self._currentTG = _no_tg + self._currentTG = self._no_tg if _payload_type == BURST_DATA_TYPE['SLOT1_VOICE']: if self._currentTG == _tg_id: - if _debug == True: - print(_ambe_frames) - print('Frame 1:', ByteToHex(_ambe_frame1.tobytes())) - print('Frame 2:', ByteToHex(_ambe_frame2.tobytes())) - print('Frame 3:', ByteToHex(_ambe_frame3.tobytes())) - - if _outToFile == True: - f.write( _ambe_frame1.tobytes() ) - f.write( _ambe_frame2.tobytes() ) - f.write( _ambe_frame3.tobytes() ) - - if _outToUDP == True: - sock.sendto(_ambe_frame1.tobytes(), (_gateway, _gateway_port)) - sock.sendto(_ambe_frame2.tobytes(), (_gateway, _gateway_port)) - sock.sendto(_ambe_frame3.tobytes(), (_gateway, _gateway_port)) - - + self.outputFrames(_ambe_frames, _ambe_frame1, _ambe_frame2, _ambe_frame3) if _payload_type == BURST_DATA_TYPE['SLOT2_VOICE']: if self._currentTG == _tg_id: - if _debug == True: - print(_ambe_frames) - print('Frame 1:', ByteToHex(_ambe_frame1.tobytes())) - print('Frame 2:', ByteToHex(_ambe_frame2.tobytes())) - print('Frame 3:', ByteToHex(_ambe_frame3.tobytes())) - - if _outToFile == True: - f.write( _ambe_frame1.tobytes() ) - f.write( _ambe_frame2.tobytes() ) - f.write( _ambe_frame3.tobytes() ) - - if _outToUDP == True: - sock.sendto(_ambe_frame1.tobytes(), (_gateway, _gateway_port)) - sock.sendto(_ambe_frame2.tobytes(), (_gateway, _gateway_port)) - sock.sendto(_ambe_frame3.tobytes(), (_gateway, _gateway_port)) + self.outputFrames(_ambe_frames, _ambe_frame1, _ambe_frame2, _ambe_frame3) + else: if _payload_type == BURST_DATA_TYPE['VOICE_HEAD']: _dst_sub = get_info(int_id(_dst_sub), talkgroup_ids) print('Ignored Voice Transmission Start on TS {} and TG {}'.format(_ts, _dst_sub)) + def outputFrames(self, _ambe_frames, _ambe_frame1, _ambe_frame2, _ambe_frame3): + if self._debug == True: + print(_ambe_frames) + print('Frame 1:', self.ByteToHex(_ambe_frame1.tobytes())) + print('Frame 2:', self.ByteToHex(_ambe_frame2.tobytes())) + print('Frame 3:', self.ByteToHex(_ambe_frame3.tobytes())) + + if self._outToFile == True: + f.write( _ambe_frame1.tobytes() ) + f.write( _ambe_frame2.tobytes() ) + f.write( _ambe_frame3.tobytes() ) + + if self._outToUDP == True: + self._sock.sendto(_ambe_frame1.tobytes(), (self._gateway, self._gateway_port)) + self._sock.sendto(_ambe_frame2.tobytes(), (self._gateway, self._gateway_port)) + self._sock.sendto(_ambe_frame3.tobytes(), (self._gateway, self._gateway_port)) -import thread - -# -# Define a function for the thread -# Use netcat to dynamically change the TGs that are forwarded to Allstar -# echo "x,y,z" | nc 127.0.0.1 1235 -# -def remote_control(port): - s = socket.socket() # Create a socket object - host = socket.gethostname() # Get local machine name - s.bind((host, port)) # Bind to the port - - s.listen(5) # Now wait for client connection. - print('listening on port ', host, port) - while True: - c, addr = s.accept() # Establish connection with client. - print( 'Got connection from', addr ) - tgs = c.recv(1024) - if tgs: - _tg_filter = map(int, tgs.split(',')) - print( 'New TGs=', _tg_filter ) - c.close() # Close the connection -try: - thread.start_new_thread( remote_control, (_remote_control_port, ) ) -except: - print( "Error: unable to start thread" ) + # + # Define a function for the thread + # Use netcat to dynamically change the TGs that are forwarded to Allstar + # echo "x,y,z" | nc 127.0.0.1 1235 + # + def remote_control(self, port): + s = socket.socket() # Create a socket object + host = socket.gethostname() # Get local machine name + s.bind((host, port)) # Bind to the port + + s.listen(5) # Now wait for client connection. + print('Remote control is listening on:', host, port) + while True: + c, addr = s.accept() # Establish connection with client. + print( 'Got connection from', addr ) + tgs = c.recv(1024) + if tgs: + self._tg_filter = map(int, tgs.split(',')) + print( 'New TGs=', self._tg_filter ) + c.close() # Close the connection