diff --git a/hb_bridge_all.py b/hb_bridge_all.py index 472d172..244bf65 100755 --- a/hb_bridge_all.py +++ b/hb_bridge_all.py @@ -134,13 +134,13 @@ class bridgeallSYSTEM(HBSYSTEM): # Is this is a new call stream? if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']): self.STATUS['RX_START'] = pkt_time - self._logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \ + logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot) # Final actions - Is this a voice terminator? if (_frame_type == hb_const.HBPF_DATA_SYNC) and (_dtype_vseq == hb_const.HBPF_SLT_VTERM) and (self.STATUS[_slot]['RX_TYPE'] != hb_const.HBPF_SLT_VTERM): call_duration = pkt_time - self.STATUS['RX_START'] - self._logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \ + logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration) # Mark status variables for use later @@ -162,39 +162,39 @@ class bridgeallSYSTEM(HBSYSTEM): if self._CONFIG['GLOBAL']['USE_ACL']: if not acl_check(_rf_src, self._CONFIG['GLOBAL']['SUB_ACL']): if self._laststrid != _stream_id: - self._logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s FROM SUBSCRIBER %s BY GLOBAL ACL', _target_system, int_id(_stream_id), int_id(_rf_src)) + logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s FROM SUBSCRIBER %s BY GLOBAL ACL', _target_system, int_id(_stream_id), int_id(_rf_src)) self._laststrid = _stream_id return if _slot == 1 and not acl_check(_dst_id, self._CONFIG['GLOBAL']['TG1_ACL']): if self._laststrid != _stream_id: - self._logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY GLOBAL TS1 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) + logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY GLOBAL TS1 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) self._laststrid = _stream_id return if _slot == 2 and not acl_check(_dst_id, self._CONFIG['GLOBAL']['TG2_ACL']): if self._laststrid != _stream_id: - self._logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY GLOBAL TS2 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) + logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY GLOBAL TS2 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) self._laststrid = _stream_id return if self._target_system['USE_ACL']: if not acl_check(_rf_src, _target_system['SUB_ACL']): if self._laststrid != _stream_id: - self._logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s FROM SUBSCRIBER %s BY SYSTEM ACL', _target_system, int_id(_stream_id), int_id(_rf_src)) + logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s FROM SUBSCRIBER %s BY SYSTEM ACL', _target_system, int_id(_stream_id), int_id(_rf_src)) self._laststrid = _stream_id return if _slot == 1 and not acl_check(_dst_id, _target_system['TG1_ACL']): if self._laststrid != _stream_id: - self._logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY SYSTEM TS1 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) + logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY SYSTEM TS1 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) self._laststrid = _stream_id return if _slot == 2 and not acl_check(_dst_id, _target_system['TG2_ACL']): if self._laststrid != _stream_id: - self._logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY SYSTEM TS2 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) + logger.debug('(%s) CALL DROPPED ON EGRESS WITH STREAM ID %s ON TGID %s BY SYSTEM TS2 ACL', _target_system, int_id(_stream_id), int_id(_dst_id)) self._laststrid = _stream_id return self._laststrid = _stream_id systems[_target].send_system(_data) - #self._logger.debug('(%s) Packet routed to system: %s', self._system, _target) + #logger.debug('(%s) Packet routed to system: %s', self._system, _target) #************************************************ @@ -256,7 +256,7 @@ if __name__ == '__main__': logger.critical('%s FATAL: Instance is mode \'OPENBRIDGE\', \n\t\t...Which would be tragic for Bridge All, since it carries multiple call\n\t\tstreams simultaneously. hb_bridge_all.py onlyl works with MMDVM-based systems', system) sys.exit('hb_bridge_all.py cannot function with systems that are not MMDVM devices. System {} is configured as an OPENBRIDGE'.format(system)) else: - systems[system] = HBSYSTEM(system, CONFIG, report_server) + systems[system] = bridgeallSYSTEM(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]) diff --git a/hb_confbridge.py b/hb_confbridge.py index fa4a78a..19ed0c7 100755 --- a/hb_confbridge.py +++ b/hb_confbridge.py @@ -169,9 +169,20 @@ def stream_trimmer_loop(): _slot = systems[system].STATUS[slot] if _slot['RX_TYPE'] != hb_const.HBPF_SLT_VTERM and _slot['RX_TIME'] < _now - 5: _slot['RX_TYPE'] = hb_const.HBPF_SLT_VTERM - logger.info('(%s) *TIME OUT* STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \ + logger.info('(%s) *TIME OUT* RX STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \ system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_RFS']), int_id(_slot['RX_TGID']), slot, _slot['RX_TIME'] - _slot['RX_START']) - systems[system]._report.send_bridgeEvent('GROUP VOICE,END,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_PEER']), int_id(_slot['RX_RFS']), slot, int_id(_slot['RX_TGID']), _slot['RX_TIME'] - _slot['RX_START'])) + if CONFIG['REPORTS']['REPORT']: + systems[system]._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['RX_STREAM_ID']), int_id(_slot['RX_PEER']), int_id(_slot['RX_RFS']), slot, int_id(_slot['RX_TGID']), _slot['RX_TIME'] - _slot['RX_START'])) + + for slot in range(1,3): + _slot = systems[system].STATUS[slot] + if _slot['TX_TYPE'] != hb_const.HBPF_SLT_VTERM and _slot['TX_TIME'] < _now - 5: + _slot['TX_TYPE'] = hb_const.HBPF_SLT_VTERM + logger.info('(%s) *TIME OUT* TX STREAM ID: %s SUB: %s TGID %s, TS %s, Duration: %s', \ + system, int_id(_slot['TX_STREAM_ID']), int_id(_slot['TX_RFS']), int_id(_slot['TX_TGID']), slot, _slot['TX_TIME'] - _slot['TX_START']) + if CONFIG['REPORTS']['REPORT']: + systems[system]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(system, int_id(_slot['TX_STREAM_ID']), int_id(_slot['TX_PEER']), int_id(_slot['TX_RFS']), slot, int_id(_slot['TX_TGID']), _slot['TX_TIME'] - _slot['TX_START'])) + # OBP systems # We can't delete items from a dicationry that's being iterated, so we have to make a temporarly list of entrys to remove later if CONFIG['SYSTEMS'][system]['MODE'] == 'OPENBRIDGE': @@ -189,11 +200,10 @@ def stream_trimmer_loop(): else: logger.info('(%s) *TIME OUT* STREAM ID: %s SUB: %s PEER: %s TGID: %s TS 1 Duration: %s', \ system, int_id(stream_id), get_alias(int_id(_system['RFS']), subscriber_ids), get_alias(int_id(_config['NETWORK_ID']), peer_ids), get_alias(int_id(_system['TGID']), talkgroup_ids), _system['LAST'] - _system['START']) - # self._report.send_bridgeEvent('GROUP VOICE,END,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration)) removed = systems[system].STATUS.pop(stream_id) else: logger.error('(%s) Attemped to remove OpenBridge Stream ID %s not in the Stream ID list: %s', system, int_id(stream_id), [id for id in systems[system].STATUS]) - + #print(systems[system].STATUS) class routerOBP(OPENBRIDGE): def __init__(self, _name, _config, _report): @@ -232,8 +242,7 @@ class routerOBP(OPENBRIDGE): logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot) if CONFIG['REPORTS']['REPORT']: - self._report.send_bridgeEvent('GROUP VOICE,START,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id))) - + self._report.send_bridgeEvent('GROUP VOICE,START,RX,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id))) self.STATUS[_stream_id]['LAST'] = pkt_time @@ -340,6 +349,7 @@ class routerOBP(OPENBRIDGE): _target_status[_target['TS']]['TX_TGID'] = _target['TGID'] _target_status[_target['TS']]['TX_STREAM_ID'] = _stream_id _target_status[_target['TS']]['TX_RFS'] = _rf_src + _target_status[_target['TS']]['TX_PEER'] = _peer_id # Generate LCs (full and EMB) for the TX stream dst_lc = self.STATUS[_stream_id]['LC'][0:3] + _target['TGID'] + _rf_src _target_status[_target['TS']]['TX_H_LC'] = bptc.encode_header_lc(dst_lc) @@ -347,9 +357,12 @@ class routerOBP(OPENBRIDGE): _target_status[_target['TS']]['TX_EMB_LC'] = bptc.encode_emblc(dst_lc) logger.debug('(%s) Generating TX FULL and EMB LCs for HomeBrew destination: System: %s, TS: %s, TGID: %s', self._system, _target['SYSTEM'], _target['TS'], int_id(_target['TGID'])) logger.info('(%s) Conference Bridge: %s, Call Bridged to HBP System: %s TS: %s, TGID: %s', self._system, _bridge, _target['SYSTEM'], _target['TS'], int_id(_target['TGID'])) + if CONFIG['REPORTS']['REPORT']: + systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,START,TX,{},{},{},{},{},{}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']))) # Set other values for the contention handler to test next time there is a frame to forward _target_status[_target['TS']]['TX_TIME'] = pkt_time + _target_status[_target['TS']]['TX_TYPE'] = _dtype_vseq # Handle any necessary re-writes for the destination if _system['TS'] != _target['TS']: @@ -371,6 +384,8 @@ class routerOBP(OPENBRIDGE): # Create a voice terminator packet (FULL LC) elif _frame_type == hb_const.HBPF_DATA_SYNC and _dtype_vseq == hb_const.HBPF_SLT_VTERM: dmrbits = _target_status[_target['TS']]['TX_T_LC'][0:98] + dmrbits[98:166] + _target_status[_target['TS']]['TX_T_LC'][98:197] + if CONFIG['REPORTS']['REPORT']: + systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']), 1)) # Create a Burst B-E packet (Embedded LC) elif _dtype_vseq in [1,2,3,4]: dmrbits = dmrbits[0:116] + _target_status[_target['TS']]['TX_EMB_LC'][_dtype_vseq] + dmrbits[148:264] @@ -389,7 +404,7 @@ class routerOBP(OPENBRIDGE): logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration) if CONFIG['REPORTS']['REPORT']: - self._report.send_bridgeEvent('GROUP VOICE,END,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration)) + self._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration)) removed = self.STATUS.pop(_stream_id) logger.debug('(%s) OpenBridge sourced call stream end, remove terminated Stream ID: %s', self._system, int_id(_stream_id)) if not removed: @@ -411,6 +426,7 @@ class routerHBP(HBSYSTEM): 'RX_RFS': '\x00', 'TX_RFS': '\x00', 'RX_PEER': '\x00', + 'TX_PEER': '\x00', 'RX_STREAM_ID': '\x00', 'TX_STREAM_ID': '\x00', 'RX_TGID': '\x00\x00\x00', @@ -418,6 +434,7 @@ class routerHBP(HBSYSTEM): 'RX_TIME': time(), 'TX_TIME': time(), 'RX_TYPE': hb_const.HBPF_SLT_VTERM, + 'TX_TYPE': hb_const.HBPF_SLT_VTERM, 'RX_LC': '\x00', 'TX_H_LC': '\x00', 'TX_T_LC': '\x00', @@ -435,6 +452,7 @@ class routerHBP(HBSYSTEM): 'RX_RFS': '\x00', 'TX_RFS': '\x00', 'RX_PEER': '\x00', + 'TX_PEER': '\x00', 'RX_STREAM_ID': '\x00', 'TX_STREAM_ID': '\x00', 'RX_TGID': '\x00\x00\x00', @@ -442,6 +460,7 @@ class routerHBP(HBSYSTEM): 'RX_TIME': time(), 'TX_TIME': time(), 'RX_TYPE': hb_const.HBPF_SLT_VTERM, + 'TX_TYPE': hb_const.HBPF_SLT_VTERM, 'RX_LC': '\x00', 'TX_H_LC': '\x00', 'TX_T_LC': '\x00', @@ -472,7 +491,7 @@ class routerHBP(HBSYSTEM): logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot) if CONFIG['REPORTS']['REPORT']: - self._report.send_bridgeEvent('GROUP VOICE,START,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id))) + self._report.send_bridgeEvent('GROUP VOICE,START,RX,{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id))) # If we can, use the LC from the voice header as to keep all options intact if _frame_type == hb_const.HBPF_DATA_SYNC and _dtype_vseq == hb_const.HBPF_SLT_VHEAD: @@ -583,6 +602,7 @@ class routerHBP(HBSYSTEM): _target_status[_target['TS']]['TX_TGID'] = _target['TGID'] _target_status[_target['TS']]['TX_STREAM_ID'] = _stream_id _target_status[_target['TS']]['TX_RFS'] = _rf_src + _target_status[_target['TS']]['TX_PEER'] = _peer_id # Generate LCs (full and EMB) for the TX stream dst_lc = self.STATUS[_slot]['RX_LC'][0:3] + _target['TGID'] + _rf_src _target_status[_target['TS']]['TX_H_LC'] = bptc.encode_header_lc(dst_lc) @@ -590,9 +610,12 @@ class routerHBP(HBSYSTEM): _target_status[_target['TS']]['TX_EMB_LC'] = bptc.encode_emblc(dst_lc) logger.debug('(%s) Generating TX FULL and EMB LCs for HomeBrew destination: System: %s, TS: %s, TGID: %s', self._system, _target['SYSTEM'], _target['TS'], int_id(_target['TGID'])) logger.info('(%s) Conference Bridge: %s, Call Bridged to HBP System: %s TS: %s, TGID: %s', self._system, _bridge, _target['SYSTEM'], _target['TS'], int_id(_target['TGID'])) + if CONFIG['REPORTS']['REPORT']: + systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,START,TX,{},{},{},{},{},{}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']))) # Set other values for the contention handler to test next time there is a frame to forward _target_status[_target['TS']]['TX_TIME'] = pkt_time + _target_status[_target['TS']]['TX_TYPE'] = _dtype_vseq # Handle any necessary re-writes for the destination if _system['TS'] != _target['TS']: @@ -614,6 +637,8 @@ class routerHBP(HBSYSTEM): # Create a voice terminator packet (FULL LC) elif _frame_type == hb_const.HBPF_DATA_SYNC and _dtype_vseq == hb_const.HBPF_SLT_VTERM: dmrbits = _target_status[_target['TS']]['TX_T_LC'][0:98] + dmrbits[98:166] + _target_status[_target['TS']]['TX_T_LC'][98:197] + if CONFIG['REPORTS']['REPORT']: + systems[_target['SYSTEM']]._report.send_bridgeEvent('GROUP VOICE,END,TX,{},{},{},{},{},{},{:.2f}'.format(_target['SYSTEM'], int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _target['TS'], int_id(_target['TGID']), 1)) # Create a Burst B-E packet (Embedded LC) elif _dtype_vseq in [1,2,3,4]: dmrbits = dmrbits[0:116] + _target_status[_target['TS']]['TX_EMB_LC'][_dtype_vseq] + dmrbits[148:264] @@ -632,7 +657,7 @@ class routerHBP(HBSYSTEM): logger.info('(%s) *CALL END* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) TGID %s (%s), TS %s, Duration: %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot, call_duration) if CONFIG['REPORTS']['REPORT']: - self._report.send_bridgeEvent('GROUP VOICE,END,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration)) + self._report.send_bridgeEvent('GROUP VOICE,END,RX,{},{},{},{},{},{},{:.2f}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), call_duration)) # # Begin in-band signalling for call end. This has nothign to do with routing traffic directly. diff --git a/hb_config.py b/hb_config.py index c3e3ef6..f8bc619 100755 --- a/hb_config.py +++ b/hb_config.py @@ -188,6 +188,7 @@ def build_config(_config_file): }}) CONFIG['SYSTEMS'][section].update({'STATS': { 'CONNECTION': 'NO', # NO, RTPL_SENT, AUTHENTICATED, CONFIG-SENT, YES + 'CONNECTED': None, 'PINGS_SENT': 0, 'PINGS_ACKD': 0, 'NUM_OUTSTANDING': 0, diff --git a/hb_parrot.py b/hb_parrot.py index 5173adf..4ed1870 100755 --- a/hb_parrot.py +++ b/hb_parrot.py @@ -59,10 +59,10 @@ __status__ = 'pre-alpha' # Module gobal varaibles class parrot(HBSYSTEM): - + def __init__(self, _name, _config, _report): HBSYSTEM.__init__(self, _name, _config, _report) - + # Status information for the system, TS1 & TS2 # 1 & 2 are "timeslot" # In TX_EMB_LC, 2-5 are burst B-E @@ -118,16 +118,15 @@ class parrot(HBSYSTEM): pkt_time = time() dmrpkt = _data[20:53] _bits = int_id(_data[15]) - if _call_type == 'group': - + # Is this is a new call stream? if (_stream_id != self.STATUS[_slot]['RX_STREAM_ID']): self.STATUS['RX_START'] = pkt_time logger.info('(%s) *CALL START* STREAM ID: %s SUB: %s (%s) REPEATER: %s (%s) TGID %s (%s), TS %s', \ self._system, int_id(_stream_id), get_alias(_rf_src, subscriber_ids), int_id(_rf_src), get_alias(_peer_id, peer_ids), int_id(_peer_id), get_alias(_dst_id, talkgroup_ids), int_id(_dst_id), _slot) - - + + # Final actions - Is this a voice terminator? if (_frame_type == hb_const.HBPF_DATA_SYNC) and (_dtype_vseq == hb_const.HBPF_SLT_VTERM) and (self.STATUS[_slot]['RX_TYPE'] != hb_const.HBPF_SLT_VTERM): call_duration = pkt_time - self.STATUS['RX_START'] @@ -140,13 +139,13 @@ class parrot(HBSYSTEM): self.send_system(i) sleep(0.06) self.CALL_DATA = [] - + else: if not self.CALL_DATA: logger.info('(%s) Receiving transmission to be played back from subscriber: %s', self._system, int_id(_rf_src)) self.CALL_DATA.append(_data) - - + + # Mark status variables for use later self.STATUS[_slot]['RX_RFS'] = _rf_src self.STATUS[_slot]['RX_TYPE'] = _dtype_vseq @@ -225,7 +224,7 @@ if __name__ == '__main__': logger.critical('%s FATAL: Instance is mode \'OPENBRIDGE\', \n\t\t...Which would be tragic for parrot, since it carries multiple call\n\t\tstreams simultaneously. hb_parrot.py onlyl works with MMDVM-based systems', system) sys.exit('hb_parrot.py cannot function with systems that are not MMDVM devices. System {} is configured as an OPENBRIDGE'.format(system)) else: - systems[system] = HBSYSTEM(system, CONFIG, report_server) + systems[system] = parrot(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]) diff --git a/hblink.py b/hblink.py index fdd422a..b9b31a3 100755 --- a/hblink.py +++ b/hblink.py @@ -391,6 +391,7 @@ class HBSYSTEM(DatagramProtocol): # Build the configuration data strcuture for the peer self._peers.update({_peer_id: { 'CONNECTION': 'RPTL-RECEIVED', + 'CONNECTED': time(), 'PINGS_RECEIVED': 0, 'LAST_PING': time(), 'SOCKADDR': _sockaddr, @@ -464,6 +465,7 @@ class HBSYSTEM(DatagramProtocol): and self._peers[_peer_id]['SOCKADDR'] == _sockaddr: _this_peer = self._peers[_peer_id] _this_peer['CONNECTION'] = 'YES' + _this_peer['CONNECTED'] = time() _this_peer['LAST_PING'] = time() _this_peer['CALLSIGN'] = _data[8:16] _this_peer['RX_FREQ'] = _data[16:25] @@ -529,7 +531,7 @@ class HBSYSTEM(DatagramProtocol): _frame_type = (_bits & 0x30) >> 4 _dtype_vseq = (_bits & 0xF) # data, 1=voice header, 2=voice terminator; voice, 0=burst A ... 5=burst F _stream_id = _data[16:20] - logger.debug('(%s) DMRD - Sequence: %s, RF Source: %s, Destination ID: %s', self._system, int_id(_seq), int_id(_rf_src), int_id(_dst_id)) + #logger.debug('(%s) DMRD - Sequence: %s, RF Source: %s, Destination ID: %s', self._system, int_id(_seq), int_id(_rf_src), int_id(_dst_id)) # ACL Processing if self._CONFIG['GLOBAL']['USE_ACL']: @@ -580,6 +582,7 @@ class HBSYSTEM(DatagramProtocol): if self._config['LOOSE'] or _peer_id == self._config['RADIO_ID']: # Validate the Radio_ID unless using loose validation logger.warning('(%s) MSTNAK Received. Resetting connection to the Master.', self._system) self._stats['CONNECTION'] = 'NO' # Disconnect ourselves and re-register + self._stats['CONNECTED'] = time() elif _command == 'RPTA': # Actually RPTACK -- an ACK from the master # Depending on the state, an RPTACK means different things, in each clause, we check and/or set the state @@ -628,6 +631,7 @@ class HBSYSTEM(DatagramProtocol): logger.info('(%s) Sent options: (%s)', self._system, self._config['OPTIONS']) else: self._stats['CONNECTION'] = 'YES' + self._stats['CONNECTED'] = time() logger.info('(%s) Connection to Master Completed', self._system) else: self._stats['CONNECTION'] = 'NO' @@ -638,6 +642,7 @@ class HBSYSTEM(DatagramProtocol): if self._config['LOOSE'] or _peer_id == self._config['RADIO_ID']: # Validate the Radio_ID unless using loose validation logger.info('(%s) Repeater Options Accepted', self._system) self._stats['CONNECTION'] = 'YES' + self._stats['CONNECTED'] = time() logger.info('(%s) Connection to Master Completed with options', self._system) else: self._stats['CONNECTION'] = 'NO'