TIMESLOT TRANSLATION WORKS!
This commit is contained in:
parent
324c16660c
commit
648569eb91
61
bridge.py
61
bridge.py
@ -47,6 +47,13 @@ __email__ = 'n0mjs@me.com'
|
||||
__status__ = 'beta'
|
||||
|
||||
|
||||
BURST_DATA_TYPE = {
|
||||
'VOICE_HEAD': '\x01',
|
||||
'VOICE_TERM': '\x02',
|
||||
'SLOT1_VOICE': '\x0A',
|
||||
'SLOT2_VOICE': '\x8A'
|
||||
}
|
||||
|
||||
# Notes and pieces of next steps...
|
||||
# RPT_WAKE_UP = b'\x85' + NETWORK[_network]['LOCAL']['RADIO_ID] + b'\x00\x00\x00\x01' + b'\x01' + b'\x01'
|
||||
# TS1 = 0, TS2 = 1
|
||||
@ -70,7 +77,9 @@ for _ipsc in RULES:
|
||||
for _rule in RULES[_ipsc]['GROUP_VOICE']:
|
||||
_rule['SRC_GROUP'] = hex_str_3(_rule['SRC_GROUP'])
|
||||
_rule['DST_GROUP'] = hex_str_3(_rule['DST_GROUP'])
|
||||
print()
|
||||
_rule['SRC_TS'] = _rule['SRC_TS'] - 1
|
||||
_rule['DST_TS'] = _rule['DST_TS'] - 1
|
||||
|
||||
|
||||
# Import List of Bridges
|
||||
# This is how we identify known bridges. If one of these is present
|
||||
@ -154,6 +163,30 @@ if BRIDGES:
|
||||
_tmp_data = _tmp_data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID'])
|
||||
# Re-Write the destination Group ID
|
||||
_tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP'])
|
||||
|
||||
# Re-Write IPSC timeslot value
|
||||
_call_info = int_id(_data[17:18])
|
||||
if rule['DST_TS'] == 0:
|
||||
_call_info &= ~(1 << 5)
|
||||
elif rule['DST_TS'] == 1:
|
||||
_call_info |= 1 << 5
|
||||
_call_info = chr(_call_info)
|
||||
_tmp_data = _tmp_data[:17] + _call_info + _tmp_data[18:]
|
||||
|
||||
# Re-Write DMR timeslot value
|
||||
# Determine if the slot is present, so we can translate if need be
|
||||
_burst_data_type = _data[30]
|
||||
if _burst_data_type == BURST_DATA_TYPE['SLOT1_VOICE'] or _burst_data_type == BURST_DATA_TYPE['SLOT2_VOICE']:
|
||||
_slot_valid = True
|
||||
else:
|
||||
_slot_valid = False
|
||||
# Re-Write timeslot if necessary...
|
||||
if _slot_valid:
|
||||
if rule['DST_TS'] == 0:
|
||||
_burst_data_type = BURST_DATA_TYPE['SLOT1_VOICE']
|
||||
elif rule['DST_TS'] == 1:
|
||||
_burst_data_type = BURST_DATA_TYPE['SLOT2_VOICE']
|
||||
_tmp_data = _tmp_data[:30] + _burst_data_type + _tmp_data[31:]
|
||||
|
||||
# Calculate and append the authentication hash for the target network... if necessary
|
||||
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
|
||||
@ -184,15 +217,39 @@ else:
|
||||
# timer = time()
|
||||
|
||||
for rule in RULES[_network]['GROUP_VOICE']:
|
||||
_target = rule['DST_NET']
|
||||
# Matching for rules is against the Destination Group in the SOURCE packet (SRC_GROUP)
|
||||
if rule['SRC_GROUP'] == _dst_group and rule['SRC_TS'] == _ts:
|
||||
_tmp_data = _data
|
||||
_target = rule['DST_NET']
|
||||
# Re-Write the IPSC SRC to match the target network's ID
|
||||
_tmp_data = _tmp_data.replace(_peerid, NETWORK[_target]['LOCAL']['RADIO_ID'])
|
||||
# Re-Write the destination Group ID
|
||||
_tmp_data = _tmp_data.replace(_dst_group, rule['DST_GROUP'])
|
||||
|
||||
# Re-Write IPSC timeslot value
|
||||
_call_info = int_id(_data[17:18])
|
||||
if rule['DST_TS'] == 0:
|
||||
_call_info &= ~(1 << 5)
|
||||
elif rule['DST_TS'] == 1:
|
||||
_call_info |= 1 << 5
|
||||
_call_info = chr(_call_info)
|
||||
_tmp_data = _tmp_data[:17] + _call_info + _tmp_data[18:]
|
||||
|
||||
# Re-Write DMR timeslot value
|
||||
# Determine if the slot is present, so we can translate if need be
|
||||
_burst_data_type = _data[30]
|
||||
if _burst_data_type == BURST_DATA_TYPE['SLOT1_VOICE'] or _burst_data_type == BURST_DATA_TYPE['SLOT2_VOICE']:
|
||||
_slot_valid = True
|
||||
else:
|
||||
_slot_valid = False
|
||||
# Re-Write timeslot if necessary...
|
||||
if _slot_valid:
|
||||
if rule['DST_TS'] == 0:
|
||||
_burst_data_type = BURST_DATA_TYPE['SLOT1_VOICE']
|
||||
elif rule['DST_TS'] == 1:
|
||||
_burst_data_type = BURST_DATA_TYPE['SLOT2_VOICE']
|
||||
_tmp_data = _tmp_data[:30] + _burst_data_type + _tmp_data[31:]
|
||||
|
||||
# Calculate and append the authentication hash for the target network... if necessary
|
||||
if NETWORK[_target]['LOCAL']['AUTH_ENABLED']:
|
||||
_tmp_data = self.hashed_packet(NETWORK[_target]['LOCAL']['AUTH_KEY'], _tmp_data)
|
||||
|
@ -10,14 +10,14 @@ The IPSC name must match an IPSC name from dmrlink.cfg, and any IPSC network def
|
||||
as "active" in the dmrlink.cfg *MUST* have an entry here. It may be an empty entry,
|
||||
but there must be one so that the data structure can be parsed.
|
||||
|
||||
The example below cross-patches TGID 1 on an IPSC network named "IPSC_FOO" with TGID 2
|
||||
on an IPSC network named "IPSC_BAR". Note, one entry must be made on EACH IPSC network
|
||||
(IPSC_FOO and IPSC_BAR in this example) for bridging to occur in both directions.
|
||||
The example below cross-patches TS 1/TGID 1 on an IPSC network named "IPSC_FOO" with
|
||||
TS 2/TGID 2 on an IPSC network named "IPSC_BAR". Note, one entry must be made on EACH
|
||||
IPSC network (IPSC_FOO and IPSC_BAR in this example) for bridging to occur in both
|
||||
directions.
|
||||
|
||||
THIS EXAMPLE WILL NOT WORK AS IT IS - YOU MUST SPECIFY NAMES AND GROUP IDS!!!
|
||||
|
||||
NOTES:
|
||||
* Timeslot transcoding does not yet work (SRC_TS) and (DST_TS) are ignored.
|
||||
* Only GROUP_VOICE is currently used by the bridge.py appication, the other
|
||||
types are placeholders for when it does more.
|
||||
'''
|
||||
@ -25,7 +25,7 @@ NOTES:
|
||||
RULES = {
|
||||
'IPSC_FOO': {
|
||||
'GROUP_VOICE': [
|
||||
{'SRC_GROUP': 1, 'SRC_TS': 1, 'DST_NET': 'IPSC_BAR', 'DST_GROUP': 2, 'DST_TS': 1},
|
||||
{'SRC_GROUP': 1, 'SRC_TS': 1, 'DST_NET': 'IPSC_BAR', 'DST_GROUP': 2, 'DST_TS': 2},
|
||||
# Repeat the above line for as many rules for this IPSC network as you want.
|
||||
],
|
||||
'PRIVATE_VOICE': [
|
||||
@ -37,7 +37,7 @@ RULES = {
|
||||
},
|
||||
'IPSC_BAR': {
|
||||
'GROUP_VOICE': [
|
||||
{'SRC_GROUP': 2, 'SRC_TS': 1, 'DST_NET': 'IPSC_FOO', 'DST_GROUP': 1, 'DST_TS': 1},
|
||||
{'SRC_GROUP': 2, 'SRC_TS': 2, 'DST_NET': 'IPSC_FOO', 'DST_GROUP': 1, 'DST_TS': 1},
|
||||
# Repeat the above line for as many rules for this IPSC network as you want.
|
||||
],
|
||||
'PRIVATE_VOICE': [
|
||||
|
@ -111,41 +111,11 @@ REPEAT = {
|
||||
}
|
||||
|
||||
|
||||
# Conditions for accepting certain types of messages... the cornerstone of a secure IPSC system :)
|
||||
'''
|
||||
REQ_VALID_PEER = [
|
||||
PEER_REG_REQ,
|
||||
PEER_REG_REPLY
|
||||
]
|
||||
# DMR IPSC Contants (in the RTP Payload)
|
||||
|
||||
REQ_VALID_MASTER = [
|
||||
MASTER_REG_REQ,
|
||||
MASTER_REG_REPLY
|
||||
]
|
||||
|
||||
REQ_MASTER_CONNECTED = [
|
||||
CALL_MON_STATUS,
|
||||
CALL_MON_RPT,
|
||||
CALL_MON_NACK,
|
||||
XCMP_XNL,
|
||||
GROUP_VOICE,
|
||||
PVT_VOICE,
|
||||
GROUP_DATA,
|
||||
GROUP_VOICE,
|
||||
PVT_DATA,
|
||||
RPT_WAKE_UP,
|
||||
MASTER_ALIVE_REQ,
|
||||
MASTER_ALIVE_REPLY,
|
||||
DE_REG_REQ,
|
||||
DE_REG_REPLY
|
||||
]
|
||||
|
||||
REQ_PEER_CONNECTED = [
|
||||
PEER_ALIVE_REQ,
|
||||
PEER_ALIVE_REPLY
|
||||
]
|
||||
|
||||
REQ_VALID_MASTER_OR_PEER = [
|
||||
REQ_VALID_PEER, REQ_VALID_MASTER
|
||||
]
|
||||
'''
|
||||
BURST_DATA_TYPE = {
|
||||
'VOICE_HEAD': '\x01',
|
||||
'VOICE_TERM': '\x02',
|
||||
'SLOT1_VOICE': '\x0A',
|
||||
'SLOT2_VOICE': '\x8A'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user