READY FOR TESTING
unit calls should be working on HBP and OBP systems. Also adds the ability to send TS data in OBP for unit calls to preserve timeslot routing for unit calls.
This commit is contained in:
parent
f00d29e8a0
commit
fdbfbf2362
33
bridge.py
33
bridge.py
@ -225,8 +225,8 @@ class routerOBP(OPENBRIDGE):
|
|||||||
self.name = _name
|
self.name = _name
|
||||||
self.STATUS = {}
|
self.STATUS = {}
|
||||||
|
|
||||||
# list of targets for unit (subscriber, private) calls
|
# list of self._targets for unit (subscriber, private) calls
|
||||||
self.targets = []
|
self._targets = []
|
||||||
|
|
||||||
def group_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _frame_type, _dtype_vseq, _stream_id, _data):
|
def group_received(self, _peer_id, _rf_src, _dst_id, _seq, _slot, _frame_type, _dtype_vseq, _stream_id, _data):
|
||||||
pkt_time = time()
|
pkt_time = time()
|
||||||
@ -418,7 +418,7 @@ class routerOBP(OPENBRIDGE):
|
|||||||
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)
|
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']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
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).encode(encoding='utf-8', errors='ignore'))
|
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).encode(encoding='utf-8', errors='ignore'))
|
||||||
_target_status[_stream_id]['ACTIVE']: False
|
self.STATUS[_stream_id]['ACTIVE']: False
|
||||||
logger.debug('(%s) OpenBridge sourced call stream end, remove terminated Stream ID: %s', self._system, int_id(_stream_id))
|
logger.debug('(%s) OpenBridge sourced call stream end, remove terminated Stream ID: %s', self._system, int_id(_stream_id))
|
||||||
|
|
||||||
|
|
||||||
@ -448,21 +448,20 @@ class routerOBP(OPENBRIDGE):
|
|||||||
if _dst_id in UNIT_MAP:
|
if _dst_id in UNIT_MAP:
|
||||||
if UNIT_MAP[_dst_id][0] != self._system:
|
if UNIT_MAP[_dst_id][0] != self._system:
|
||||||
self._targets = [UNIT_MAP[_dst_id][0]]
|
self._targets = [UNIT_MAP[_dst_id][0]]
|
||||||
_target_route = UNIT_MAP[_dst_id][0]
|
|
||||||
else:
|
else:
|
||||||
self._targets = []
|
self._targets = []
|
||||||
logger.debug('UNIT call to a subscriber on the same system, send nothing')
|
logger.error('UNIT call to a subscriber on the same system, send nothing')
|
||||||
else:
|
else:
|
||||||
self._targets = list(systems)
|
self._targets = list(UNIT)
|
||||||
self._targets.remove(self._system)
|
self._targets.remove(self._system)
|
||||||
_target_route = 'FLOOD'
|
|
||||||
|
|
||||||
# This is a new call stream, so log & report
|
# This is a new call stream, so log & report
|
||||||
self.STATUS['START'] = pkt_time
|
self.STATUS['START'] = pkt_time
|
||||||
logger.info('(%s) *UNIT CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) UNIT: %s (%s), TS: %s, FORWARD: %s', \
|
logger.info('(%s) *UNIT CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) UNIT: %s (%s), TS: %s, FORWARD: %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, _target_route)
|
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, self._targets)
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
self._report.send_bridgeEvent('UNIT VOICE,START,RX,{},{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), _target_route).encode(encoding='utf-8', errors='ignore'))
|
self._report.send_bridgeEvent('UNIT VOICE,START,RX,{},{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), self._targets).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
for _target in self._targets:
|
for _target in self._targets:
|
||||||
_target_status = systems[_target].STATUS
|
_target_status = systems[_target].STATUS
|
||||||
@ -480,13 +479,14 @@ class routerOBP(OPENBRIDGE):
|
|||||||
'ACTIVE': True
|
'ACTIVE': True
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('(%s) Unit call bridged to OBP System: %s TS: %s, TGID: %s', self._system, _target, _slot, int_id(_dst_id))
|
logger.info('(%s) Unit call bridged to OBP System: %s TS: %s, TGID: %s', self._system, _target, _slot if _target_system['BOTH_SLOTS'] else 1, int_id(_dst_id))
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[_target]._report.send_bridgeEvent('UNIT VOICE,START,TX,{},{},{},{},{},{}'.format(_target, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)).encode(encoding='utf-8', errors='ignore'))
|
systems[_target]._report.send_bridgeEvent('UNIT VOICE,START,TX,{},{},{},{},{},{}'.format(_target, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
# Record the time of this packet so we can later identify a stale stream
|
# Record the time of this packet so we can later identify a stale stream
|
||||||
_target_status[_stream_id]['LAST'] = pkt_time
|
_target_status[_stream_id]['LAST'] = pkt_time
|
||||||
# Clear the TS bit -- all OpenBridge streams are effectively on TS1
|
# Clear the TS bit and follow propper OBP definition, unless "BOTH_SLOTS" is set. This only works for unit calls.
|
||||||
|
if not _target_system['BOTH_SLOTS']:
|
||||||
_tmp_bits = _bits & ~(1 << 7)
|
_tmp_bits = _bits & ~(1 << 7)
|
||||||
|
|
||||||
# Assemble transmit HBP packet
|
# Assemble transmit HBP packet
|
||||||
@ -583,8 +583,8 @@ class routerHBP(HBSYSTEM):
|
|||||||
HBSYSTEM.__init__(self, _name, _config, _report)
|
HBSYSTEM.__init__(self, _name, _config, _report)
|
||||||
self.name = _name
|
self.name = _name
|
||||||
|
|
||||||
# list of targets for unit (subscriber, private) calls
|
# list of self._targets for unit (subscriber, private) calls
|
||||||
self.targets = []
|
self._targets = []
|
||||||
|
|
||||||
# Status information for the system, TS1 & TS2
|
# Status information for the system, TS1 & TS2
|
||||||
# 1 & 2 are "timeslot"
|
# 1 & 2 are "timeslot"
|
||||||
@ -931,7 +931,7 @@ class routerHBP(HBSYSTEM):
|
|||||||
logger.info('(%s) *UNIT CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) UNIT: %s (%s), TS: %s, FORWARD: %s', \
|
logger.info('(%s) *UNIT CALL START* STREAM ID: %s SUB: %s (%s) PEER: %s (%s) UNIT: %s (%s), TS: %s, FORWARD: %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, self._targets)
|
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, self._targets)
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
self._report.send_bridgeEvent('UNIT VOICE,START,RX,{},{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), _target_route).encode(encoding='utf-8', errors='ignore'))
|
self._report.send_bridgeEvent('UNIT VOICE,START,RX,{},{},{},{},{},{},{}'.format(self._system, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id), self._targets).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
for _target in self._targets:
|
for _target in self._targets:
|
||||||
|
|
||||||
@ -950,13 +950,14 @@ class routerHBP(HBSYSTEM):
|
|||||||
'ACTIVE': True
|
'ACTIVE': True
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info('(%s) Unit call bridged to OBP System: %s TS: %s, UNIT: %s', self._system, _target, _slot, int_id(_dst_id))
|
logger.info('(%s) Unit call bridged to OBP System: %s TS: %s, UNIT: %s', self._system, _target, _slot if _target_system['BOTH_SLOTS'] else 1, int_id(_dst_id))
|
||||||
if CONFIG['REPORTS']['REPORT']:
|
if CONFIG['REPORTS']['REPORT']:
|
||||||
systems[_target]._report.send_bridgeEvent('UNIT VOICE,START,TX,{},{},{},{},{},{}'.format(_target, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)).encode(encoding='utf-8', errors='ignore'))
|
systems[_target]._report.send_bridgeEvent('UNIT VOICE,START,TX,{},{},{},{},{},{}'.format(_target, int_id(_stream_id), int_id(_peer_id), int_id(_rf_src), _slot, int_id(_dst_id)).encode(encoding='utf-8', errors='ignore'))
|
||||||
|
|
||||||
# Record the time of this packet so we can later identify a stale stream
|
# Record the time of this packet so we can later identify a stale stream
|
||||||
_target_status[_stream_id]['LAST'] = pkt_time
|
_target_status[_stream_id]['LAST'] = pkt_time
|
||||||
# Clear the TS bit -- all OpenBridge streams are effectively on TS1
|
# Clear the TS bit and follow propper OBP definition, unless "BOTH_SLOTS" is set. This only works for unit calls.
|
||||||
|
if not _target_system['BOTH_SLOTS']:
|
||||||
_tmp_bits = _bits & ~(1 << 7)
|
_tmp_bits = _bits & ~(1 << 7)
|
||||||
|
|
||||||
# Assemble transmit HBP packet
|
# Assemble transmit HBP packet
|
||||||
|
@ -274,6 +274,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'),
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -48,8 +48,7 @@ BRIDGES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
'''
|
'''
|
||||||
list the names of each system that should process unit to unit (individual) calls. Processing
|
list the names of each system that should bridge unit to unit (individual) calls.
|
||||||
is both ingress and egress.
|
|
||||||
'''
|
'''
|
||||||
|
|
||||||
UNIT = ['ONE', 'TWO']
|
UNIT = ['ONE', 'TWO']
|
||||||
|
Loading…
Reference in New Issue
Block a user